我不能在run()方法中使用变量"i".有什么办法吗?
public class Main {
public static void main(String[] args) {
final int M = 100;
final int N = 4;
final int[] array = new int[M];
for(int b = 0; b < M; b++) array[b] = b;
for( int i = 0; i < N; i++) {
new Thread(new Runnable() {
public void run() {
for(int a = i*(M/N);a < (i+1)*(M/N); a++)
System.out.println("Thread "+i+":"+array[a]);
// i -> cannot refer to a non-final variable inside an inner class defined in a different method
}
}).start();
}
}
}
Run Code Online (Sandbox Code Playgroud)
Ale*_* C. 22
您可以声明一个final变量p,该变量将取i每次迭代的值.
for( int i = 0; i < N; i++) {
final int p = i;
new Thread(new Runnable() {
public void run() {
for(int a = p*(M/N);a < (p+1)*(M/N); a++)
System.out.println("Thread "+p+":"+array[a]);
}
}).start();
}
Run Code Online (Sandbox Code Playgroud)
那就对了.这是Java内部类的限制!除非将该变量声明为,否则不允许内部类访问封闭范围中的实例变量final.
所以你需要像这样实现那些代码......
for (int i = 0; i < N; i++) {
final int ii = i;
new Thread(new Runnable() {
public void run() {
for(int a = ii*(M/N);a < (ii+1)*(M/N); a++)
System.out.println("Thread "+ii+":"+array[a]);
}
}).start();
}
Run Code Online (Sandbox Code Playgroud)
这种限制的原因是为了避免Java需要实现闭包.由于ii是最终的,编译器可以通过ii在实例化时将值的副本传递给匿名内部类来实现上述内容.它存储在隐藏变量中......以便在封闭方法调用完成后使用它.
如果没有这个限制,(假设的)Java编译器需要创建一个堆对象来保存i变量.(或者至少如果它无法优化对象的话......)这就是关闭 ......在实现层面.
人们有时会错过的另一点是,如果Java允许您访问非最终版本,则此特定算法将是不正确的i.为什么?因为在线程实际启动时,外部循环很可能已经完成,并且线程将全部看到i该值N.这不是你想要在这里实现的.
UPDATE从Java 8开始,外部实例变量只需要有效最终.
| 归档时间: |
|
| 查看次数: |
13441 次 |
| 最近记录: |