这些天,看了一些书,有些代码觉得写得挺不错。匿名内部里虽然以前也学过,但是就自身来说,用得还是少。先贴出一段代码。
ArrayAsList类主要是提供了一个intArrayAsList方法,将int类型的数组转换面list。初看,返回的list并不真正拥有int [] a,是在调用get(int index)方法的时候,才从a数组中拿出相应下标的值返回去。但是,数组也是对象,也是引用传递,能保证传递过来的int [] a数组不被回收吗?如果被回收了,那再调用get(int index)不就抛异常了。对这个问题一时很困惑,于是在网上开始找资料。加上自己的一些调试,大致理解了其中的原因。
我们都知道,在方法内部定义的局部变量,会在方法执行完后而回收。但是,在方法内部定义的类却不一定在方法结束后而被回收,局部内部类的生命周期,是有可能比方法的生命周期长的。但是,如果方法执行结束,局部变量被回收,而在方法内部定义的内部类还存在,在内部类中调用了方法的局部变量,这时局部变量已经不存在,就会出错 。
对于内部类,默认有个对外部的引用。如果局部变量是个对象,不是基本类型,我们知道对象是在堆中分配内存的,基本类型是在方法栈中分配内存的。如果内部类引用的局部变量是引用类型的,就算方法执行完,方法栈被回收,内部类还保持对局部对象的引用,对象没被回收,也还说得过去。但如果局部变量是基本类型呢?基本类型是在方法栈中分配内存的,方法执行完,基本类型的局部变量必然被弹栈,方法栈被回收,基本类型的局部变量消失,那么我们内部类调用就会出错。
为了解决这个问题,我们在方法内部定义的类,不管是匿名的还是非匿名的,如果要访问方法内部的局部变量,包括参数变量,编译器都要求我们的变量是final的。根据自己的调试,更坚信这一点是正确的。java的处理机制,是将内部类引用的局部变量做了一个拷贝,放到了内部类作为内部类的一个成员。final定义的变量还是会像以前一样,方法执行完,内存该被回收的还是回收,但这个拷贝,放在内部类里,将会跟随内部类的整个生命周期。