使用外部类变量时为什么需要final修饰【转】
2017-05-23 10:11
281 查看
http://www.cnblogs.com/chenlong-50954265/p/5643770.html
我们看到匿名内部类Test$1的构造器含有两个参数,一个是指向外部类对象的引用,一个是int型变量,很显然,这里是将变量test方法中的形参a以参数的形式传进来对匿名内部类中的拷贝(变量a的拷贝)进行赋值初始化。
也就说如果局部变量的值在编译期间就可以确定,则直接在匿名内部里面创建一个拷贝。如果局部变量的值无法在编译期间确定,则通过构造器传参的方式来对拷贝进行初始化赋值。
从上面可以看出,在run方法中访问的变量a根本就不是test方法中的局部变量a。这样一来就解决了前面所说的 生命周期不一致的问题。但是新的问题又来了,既然在run方法中访问的变量a和test方法中的变量a不是同一个变量,当在run方法中改变变量a的值的话,会出现什么情况?
对,会造成数据不一致性,这样就达不到原本的意图和要求。为了解决这个问题,java编译器就限定必须将变量a限制为final变量,不允许对变量a进行更改(对于引用类型的变量,是不允许指向新的对象),这样数据不一致性的问题就得以解决了。
到这里,想必大家应该清楚为何 方法中的局部变量和形参都必须用final进行限定了。
public class Test { public static void main(String[] args) { } public void test(final int b) { final int a = 10; new Thread(){ public void run() { System.out.println(a); System.out.println(b); }; }.start(); } }
我们看到匿名内部类Test$1的构造器含有两个参数,一个是指向外部类对象的引用,一个是int型变量,很显然,这里是将变量test方法中的形参a以参数的形式传进来对匿名内部类中的拷贝(变量a的拷贝)进行赋值初始化。
也就说如果局部变量的值在编译期间就可以确定,则直接在匿名内部里面创建一个拷贝。如果局部变量的值无法在编译期间确定,则通过构造器传参的方式来对拷贝进行初始化赋值。
从上面可以看出,在run方法中访问的变量a根本就不是test方法中的局部变量a。这样一来就解决了前面所说的 生命周期不一致的问题。但是新的问题又来了,既然在run方法中访问的变量a和test方法中的变量a不是同一个变量,当在run方法中改变变量a的值的话,会出现什么情况?
对,会造成数据不一致性,这样就达不到原本的意图和要求。为了解决这个问题,java编译器就限定必须将变量a限制为final变量,不允许对变量a进行更改(对于引用类型的变量,是不允许指向新的对象),这样数据不一致性的问题就得以解决了。
到这里,想必大家应该清楚为何 方法中的局部变量和形参都必须用final进行限定了。
相关文章推荐
- Android onclicklistener中使用外部类变量时为什么需要final修饰【转】
- 局部内部类访问外部变量为什么需要使用final修饰
- 为什么内部类访问的外部变量需要使用final修饰
- 为什么内部类访问的外部变量需要使用final修饰
- 为什么内部类访问的外部变量需要使用final修饰
- 为什么内部类访问的外部变量需要使用final修饰
- 匿名内部类使用外部类变量必须用final修饰?
- 内部类访问的外部变量需要使用final修饰解释原因
- 使用匿名内部类,隐式调用外部变量,外部变量需要final修饰
- 为什么Java匿名内部类访问的外部局部变量或参数需要被final修饰
- 匿名内部类使用外部的局部变量时为什么一定要final修饰
- 为什么一个匿名内部类使用一个在其外部定的对象必须使用final修饰
- 为什么内部类访问局部变量需要加final修饰?
- 为什么接口中的常量必须使用public static final修饰
- tips:为什么接口中的常量必须使用public static final修饰?
- 为什么局部变量必须以final修饰(或者有final实效:java8)才可以在内部类中使用?
- java匿名内部类使用外部变量时,外部变量必须是final,为什么?
- 为什么在内部类中用外部类的对象要用final修饰
- Java为什么匿名内部类参数引用需要用final进行修饰?
- 匿名内部类使用了一个在其外部定义的对象,为什么编译器会要求其参数引用是final呢