书接上文
问题:局部内部类访问局部变量必须用final修饰,为什么?
当调用这个方法时,局部变量如果没有用final修饰,他的生命周期和方法的生命周期是一样的,当方法被调用时会入栈,方法结束后会弹栈(出栈),这个局部变量会消失,那么如果局部内部类对象还没有马上消失且想用这个局部变量,显然已经无法使用了,如果用final修饰会在类加载的时候进入常量池,即使方法弹栈,常量池的常量还在,也就可以继续使用了。
注意:在JDK1.8中取消了在局部内部类中使用的变量必须显示的使用final修饰。所以说在前面说内部类的时候没加final,编译器会默认为这个变量加上final。其实前面举的例子的int x = 10,Java默认在前面加了final,在1.8之前我们是要手动添加的。
public class Demo2 { public static void main(String[] args) { Outer outer = new Outer(); //outer.innerPrint(); outer.show(4); } } class Outer { //建立方法内部类 public void show(final int y)//在1.7(包括1.7)之前,参数要加final { final int x = 6;//在1.7(包括1.7)之前,变量要加final class Inner { public void print() { System.out.println("方法内部类"+x+y); } } Inner inner = new Inner(); inner.print(); } } /* 结果: 方法内部类64 */ /*16行,如果前面不加final修饰,它的生命周期和此方法的生命周期一样,当方法结束,x就会被销毁。那么局部内部类 对象(Inner还没有消失,因为方法执行完了生命周期会结束(出栈),但是局部内部类对象还要被回收,所以这个生命周 期比方法的生命周期更长)没有消失,当方法结束后,内部类Inner就会出错了*/ /*final:在Java中,栈里面会有一块区域叫常量池,在变量前面加final,这个变量就会是一个常量,加到常量池里面, 这样的话这个变量的生命周期会更长*/
内部类的作用
每个内部类都能独立的继承自一个(接口的)实现,所以无论外部类是否已经继承了某个(接口的)实现,对于内部类都没有影响。如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决。从这个角度看,内部类使得多重继承的解决方案变得完整。接口解决了部分问题,而内部类有效地实现了“多重继承”。
就像这样(Java只能单继承,但有了内部类,就可以实现多继承)
class B { } class A extends B { class C extends B { } }
依赖外部类对象的:成员内部类、方法内部类、匿名内部类
不依赖外部对象的:静态内部类
所以,我们在项目开发中优先考虑静态内部类,因为它不依赖外部对象,这就考虑到内存泄漏的问题了。比如说1是外部类,且生命周期比较短,2是内部类,且生命周期比较长,当2一直在用的时候,1已经结束了,这就是一个Bug后面会说,这就叫内存泄漏。如果优先选择静态内部类,就不会产生内存泄漏,因为此内部类不依赖外部对象
