为什么使用for-each时,循环变量有效地结束? [重复]

问题描述 投票:5回答:2

此问题已经在这里有了答案:

  • 情况1:使用for-each循环时可以使用:
    private void m10(String[] arr) {
        for (String s : arr) {
            Supplier<String> supplier = () -> {
                System.out.println(s);
                return null;
            };
            supplier.get();
        }
    }

    private void m10(Object[] arr) {
        for (Object s : arr) {
            Supplier<String> supplier = () -> {
                System.out.println(s);
                return null;
            };
            supplier.get();
        }
    }
  • 情况2:它将捕获编译时错误
    private void m11(String[] arr) {
        for (int i = 0; i < arr.length; i++) {
            Supplier<String> supplier = () -> {
                System.out.println(arr[i]);
                return null;
            };
            supplier.get();
        }
    }

在情况2中,我知道变量i并不是有效的最终变量,因为其值在循环迭代之间发生了变化。但是我不明白为什么lambda可以在情况1下工作。

java lambda final
2个回答
7
投票

s从不更改(s = ...)。因此,编译器说“是的,理论上我们可以将其标记为final。这就是有效最终的意思。即您没有将其标记为final,但可以并且仍会编译。

如果您想了解增强的for循环:

for (String s : arr)

该变量不会超出for的范围,也不会被重新分配。即它是not

String s = null;
for (int i = 0; i < arr.length; i++) {
    s = arr[i];
    ...
}

变量是在循环内部创建的,因此其作用域仅限于循环。它不会重复使用,而是在每次迭代时都丢弃并重新创建:

for (int i = 0; i < arr.length; i++) {
    String s = arr[i];
    ...
}

仔细看两个例子。首先,您无法编写final String s = null;,因为我们在循环s = arr[i];期间重新分配了它。但是在第二个示例中我们可以,因为变量s仅在一次迭代中才知道,然后又被丢弃。所以final String s = arr[i];很好。

作为旁注,这也解释了为什么循环后不能使用s。它是未知的并且已经被销毁,其范围仅限于循环。


4
投票

因为s的范围是单个迭代,所以没有一个s会改变值,但是每个循环迭代都会有一个有效的最终s

这就像用下面的方式编写案例2一样,可以编译

private void m11(String[] arr) {
    for (int i = 0; i < arr.length; i++) {
        String s = arr[i];
        Supplier<String> supplier = () -> {
            System.out.println(s);
            return null;
        };
        supplier.get();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.