书接上文
问题:局部内部类访问局部变量必须用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后面会说,这就叫内存泄漏。如果优先选择静态内部类,就不会产生内存泄漏,因为此内部类不依赖外部对象