java匿名内部类的参数为final类型

我之前本来在网上看过为什么java匿名内部类的参数为final类型的这方面介绍的,但是昨天写程序的时候又看到这个,突然想不起来为什么了。然后我又查了一下,但是找不到我之前看的那篇说的很详细的文章了,网上说的有点似懂非懂,后面自己推理了下才想明白。

一般我们在test.addListener(new Listener)创建这样的匿名内部类

public class Test1 {

	Listener mListener;
	interface Listener{
		void onListener(Object b);
	}
	
	void useListener() {
		final String a = new String();
		Test1 test = new Test1();
		test.addListener(new Listener() {
			
			public void onListener(Object b) {
				System.out.println(a);
			}
		});
	}

	void addListener(Listener listener){
		this.mListener = listener;
	}
	
}
编译器回把这个匿名内部类单独编译成一个类
class Test1$1
  implements Test1.Listener
{
	private final Test1 val$0;
        private final String val$a;
  Test1$1(Test1 paramTest1, String paramString)
  {
	this.val$0 = paramTest1;
	this.val$a = paramString;
  }

  public void onListener(Object paramObject)
  {
    System.out.println(this.val$a);
  }
}

它会把外部类和内部类里用到的参数通过构造函数传到内部类里,可能这是因为方法体内的参数在方法执行完后,如果没有其它地方引用的话可能就被回收掉了,所以内部类创建一个参数继续引用。

那为什么一定要是final类型呢?

假如a刚传到内部类时


这时创建了一个val$a来指向a的引用,如果a不是final类型的,假如在方法后面a又指向了另一个object


这时就造成了内部类和方法体的参数不一致,因为本质上我们在编写内部类的时候是看不到val$a这个编译器自动创建的参数,我们在内部类中还是使用a(编译器把它转换成了val$a),还是希望使用的是a指向的那个实体,而不是val$a指向的以前那个实体。

而内部类回调有不确定性,有可能在你给a重新赋值之前也可能在之后。到时可能出现两次运行不一样的结果,所以就干脆把参数设定成final不让它进行改变,这样就可以避免很多麻烦了。全局变量就不需要final了,因为内部类默认有一个外类的引用,可以直接通过外部类来使用全局变量,不需要通过构造函数传递。

这是在网上看到的一些资料,然后进行的一点推理,如果有不对的地方,欢迎大家指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值