会写bug的大佬 2022-08-30 17:29

for each循环变量赋值问题

对于普通类型来讲

 public void test() {

        List<String> strList = new ArrayList<String>();

        strList.add("乐视网");

        strList.add("财经网");

        strList.add("凤凰网");

        for(String str:strList){

            if("乐视网".equals(str)){

                str = "腾讯网";

            }

        }

        System.out.println(strList);

}
 

这段代码输出的结果是: [乐视网, 财经网, 凤凰网]
可见循环计数器只是一个中间变量,它仅仅保存了当前正在遍历的集合元素,因此对其赋值并不会改变集合元素本身。

但是,对于map、对象类型来讲

 

    public void test() {
  List<Map<String,Object>> stringList = new ArrayList<Map<String,Object>>();
      Map<String,Object> map = new HashMap<String, Object>();
      map.put("leshi", "乐视网");
      map.put("caijing", "财经网");
      map.put("fenghuang", "凤凰网");
      stringList.add(map);
      for(Map<String,Object> m:stringList){
          if("乐视网".equals(m.get("leshi"))){
              m.put("leshi", "乐视体育");
          }
      }
      System.out.println(stringList);
  }

 

这段代码输出的结果则为: [{fenghuang=凤凰网, caijing=财经网, leshi=乐视体育}]
显然原来的map的value被改变了。
这是为什么呢?

1条回答
最新 最热
阿靠北啊 2022-09-02 21:45

String类型在Java中是引用类型。
举个例子

上面三个式子,因为String是引用类型,执行前两句后,其实是相当于str1和str2两个变量同时指向同一个String类型,值为“one”。
但是str2 = “two”的意思,是str2重新被指向了一个新的变量String,值为“two”,而不是改变原来的String类型的值。
在foreach中也很好的表现了这点,str作为中间变量,遍历的同时和strList的每个遍历值同时指向同一个对象String。
但是你执行的str = “腾讯网”;这个语句,只是改变了中间变量指向新的String,而不是修改旧String的值。
而在你的第二个代码片中,使用的是Map类型。Map是一种键值对形式存在的引用类型。
foreach中m作为中间变量,同时指向了遍历的Map,而你使用的是m.put()函数,就是使用了指向的那个Map的方法,put将value改变了,所以整个集合的value跟着改变了。

这是个人的浅显理解,其实关键在于你改变值的方式其实两个代码片是不同的。
一个是直接用=改变,一个用既有的Map内含的函数改变。String类型的=并不是和基本类型一样,是普通的改变赋值,而是重新创建了一个新的对象,新的值。

举报

10