区别在于局部变量与类成员变量之间。成员变量在封闭对象的生命周期内存在,因此可以被内部类实例引用。然而,局部变量仅在方法调用期间存在,并且由编译器以不同方式处理,因为它的隐式副本被生成为内部类的成员。如果不声明局部变量为final,就可以更改它,从而由于内部类仍然引用该变量的原始值而导致细微的错误。
最终局部变量 http://www.javaspecialists.eu/archive/Issue025.html
我知道创建局部变量或变量有两个原因
参数最终。第一个原因是你不想要你的代码
更改局部变量或参数。被很多人认为
更改方法内的参数是不好的风格,因为它会使
代码不清楚。作为一种习惯,一些程序员将所有参数都设置为
“最终”以防止自己改变它们。我不这样做,
因为我发现它使我的方法签名有点难看。
当我们想要访问局部变量或
来自内部类的参数。这才是真正的原因,因为
据我所知,最终的局部变量和参数是
在 JDK 1.1 中引入到 Java 语言中。
public class Access1 {
public void f() {
final int i = 3;
Runnable runnable = new Runnable() {
public void run() {
System.out.println(i);
}
};
}
}
在 run() 方法内部,只有当我们在外部类中将 i 设置为 Final 时,我们才能访问它。为了理解其中的道理,我们必须
看看编译器做了什么。它生成两个文件,Access1.class
和 Access1$1.class。当我们用 JAD 反编译它们时,我们得到:
public class Access1 {
public Access1() {}
public void f() {
Access1$1 access1$1 = new Access1$1(this);
}
}
and
class Access1$1 implements Runnable {
Access1$1(Access1 access1) {
this$0 = access1;
}
public void run() {
System.out.println(3);
}
private final Access1 this$0;
}
由于 i 的值是最终值,因此编译器可以将其“内联”到内部
班级。让我感到不安的是,局部变量必须是最终的
由内部类访问,直到我看到上面的内容。
当局部变量的值可以根据不同的情况而改变时
内部类的实例,编译器将其添加为内部类的数据成员
内部类并让它在构造函数中初始化。这
这背后的根本原因是Java没有指针,
就像C那样。
考虑下面的类:
public class Access2 {
public void f() {
for (int i=0; i<10; i++) {
final int value = i;
Runnable runnable = new Runnable() {
public void run() {
System.out.println(value);
}
};
}
}
}
这里的问题是我们每次执行 for 循环时都必须创建一个新的本地数据成员,所以我今天有一个想法
在编码时,是将上面的代码更改为以下内容:
public class Access3 {
public void f() {
Runnable[] runners = new Runnable[10];
for (final int[] i={0}; i[0]<runners.length; i[0]++) {
runners[i[0]] = new Runnable() {
private int counter = i[0];
public void run() {
System.out.println(counter);
}
};
}
for (int i=0; i<runners.length; i++)
runners[i].run();
}
public static void main(String[] args) {
new Access3().f();
}
}
我们现在不必声明额外的最终局部变量。事实上,这或许不是真的吗?
int[] i 就像一个常见的指向 int 的 C 指针?我花了4年时间才
看到这个,但如果您听说过这个想法,我想听听您的意见
别的地方。