【问题标题】:What scope does the enhanced for loop variable have in java? [duplicate]增强的 for 循环变量在 java 中的作用域是什么? [复制]
【发布时间】:2020-05-06 15:38:53
【问题描述】:

对于 Java 中的不同类,增强型 for 循环 (EFL) 变量的范围是否不同?

当我在包含 Integers 的 ArrayList 上使用 EFL 时,我无法直接修改它们的值,但是如果我对下面代码中定义的 SimpleObjects 的 ArrayList 执行相同的操作,我可以毫无问题地更改实例变量的值。

import java.util.ArrayList;

class SimpleObject{
  public int x;
  public SimpleObject() {
    this.x = 0;
  }
}

public class Simple {
  public static void main(String args[]){
    // Create an arraylist of Integers and SimpleObjects
    ArrayList<Integer> intList     = new ArrayList<Integer>();
    ArrayList<SimpleObject> soList = new ArrayList<SimpleObject>();

    // Add some items to the arraylists
    intList.add(1);
    intList.add(2);
    soList.add(new SimpleObject());
    soList.add(new SimpleObject());

    // Loop over the arraylists and change some values
    for (Integer _int : intList) {
      _int = 3; // Why doesn't this work but so.x = 5 below does?
    }
    for(SimpleObject so : soList) {
      so.x = 5;
    }

    // Loop over the arraylists to print out values
    for (Integer _int : intList) {
      System.out.println("integer = " + _int);
    }
    for(SimpleObject so : soList) {
      System.out.println("      x = " + so.x);
    }
  }
}

实际输出:

integer = 1
integer = 2
      x = 5
      x = 5

预期输出:

integer = 3
integer = 3
      x = 5
      x = 5

所以我的问题是为什么_int = 3; 不坚持第一个 EFL,但 so.x = 5; 坚持第二个 EFL?

【问题讨论】:

  • _int 是对Integer 的引用的副本,因此您要重新分配_int 变量,它是localfor 循环迭代。一旦退出循环,_int 变量就会超出范围,Integer 对象将被垃圾收集(如果它没有被 Integer 类缓存,但那是另一回事了)。

标签: java foreach


【解决方案1】:
// Loop over the arraylists and change some values
for (Integer _int : intList) {
  _int = 3; // Why doesn't this work but so.x = 5 below does?
}
for(SimpleObject so : soList) {
  so.x = 5;
}

这是因为您将值分配给_int,但您正在更改so 中的值。赋值和改变值是完全不同的事情。

您可以通过以下示例更好地理解它:

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        final List<String> list = new ArrayList<String>();

        // Changing - will work
        list.add("Hello");
        list.add("World");

        // Assigning - won't work
        list = null;
    }
}

如果要更改intList,可以使用List:set,如下图:

import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList<Integer> intList = new ArrayList<Integer>();
        intList.add(1);
        intList.add(2);

        for (int i = 0; i < intList.size(); i++) {
            intList.set(i, 3);
        }

        // Display
        intList.stream().forEach(System.out::println);
    }
}

输出:

3
3

【讨论】:

  • 啊,这是有道理的,所以如果 Integer 类碰巧有一个 'changeValue()' 方法,那么 _int.changeValue(3) 会起作用吗?
  • 是的,你明白了。
【解决方案2】:

不同之处不在于范围规则有所不同,而是您执行了两种不同的操作:

  • so.x = 3so 引用的对象的字段x 设置为3。
  • _int = 3_int 设置为 3。

如果您将so.x = 3 更改为so = new SimpleObject,您会发现这也不会影响您迭代的列表的内容。

【讨论】:

    【解决方案3】:

    对于 Java 中的不同类,增强型 for 循环 (EFL) 变量的范围是否不同?

    没有。在for 循环或扩展for 循环中声明的变量的范围是循环体。

    为什么不 _int = 3;坚持第一个 EFL,但 so.x = 5;第二个EFL呢?

    在第二个示例中,您没有分配给循环变量so

    您正在分配给so.x。那是so 变量所引用的对象的一个​​字段。

    然后您再次遍历列表并访问您之前更新的对象。

    两个循环中的so变量是不同的变量。

    【讨论】:

      猜你喜欢
      • 2013-08-03
      • 2012-07-25
      • 1970-01-01
      • 2011-01-20
      • 1970-01-01
      • 2018-08-24
      • 2013-11-25
      • 2015-03-24
      • 1970-01-01
      相关资源
      最近更新 更多