java内部类详解
在JDK1.8之前,如果我们在匿名内部类中访问局部变量,局部变量必须用final修饰。 JDK1.8以后,我们在匿名内部类中访问局部变量。 看似不需要用final修饰,其实是语法糖(底层还是给你加上final的),就是我们不能在匿名内部类中改。 此局部变量的引用值。
错误的答案:
如果局部变量没有用final修饰,它的生命周期和方法的生命周期是一样的。 当方法出栈时,局部变量也会消失。 如果局部内部类对象还没有马上消失,你要用这个局部变量,就不用了,如果你用final修饰,类加载的时候就会进入常量池。 即使方法出栈,常量池中的常量还在,可以继续使用。
**分析:一个变量加上final能不能延长生命周期? 那么添加 final 不会导致短期内存泄漏吗? 其实传入的内部变量是匿名内部类的成员变量(通过构造函数传入)。
变量被回收不是因为方法执行了,而是GC Root是否持有对象的引用。 实际上,该变量是作为本地内部类构造参数传入的,仍然是可达的。 因此,final并不会延长变量的生命周期。
**
正确答案:
添加最终修改以保持内部和外部数据的一致性~
1、匿名内部类可以使用的变量 外部类的成员变量(被所有访问修饰符修饰的变量)。 外部方法中的局部变量(需要final修改)。 外部方法的参数(需要最终确定)。
实际上,只有第一个变量不需要声明为final。
2.匿名内部类构造函数
其实匿名内部类和所有的类一样,都有自己的构造函数,只不过这个构造函数是隐式的。
构造函数的参数:
1. 对外部对象的引用。 (这就是我们可以无条件使用外部对象的原因)
2、匿名内部类使用的局部变量或方法参数。
1.反编译前
public class Outer {
String string = ""; //外部类成员变量
void outerTest(final char ch){ //外部方法方法参数
final Integer integer = 1; //外部方法局部变量
Inner inner = new Inner() {
void innerTest() {
//在匿名内部类中均可无条件使用
System.out.println(string);
System.out.println(ch);
System.out.println(integer);
}
};
}
public static void main(String[] args) {
new Outer().outerTest(' ');
}
class Inner {
}
}
2.反编译后
//匿名内部类
class Outer$1extends Outer.Inner
{
//构造函数,传入的便是外部类引用,以及外部方法的局部变量和方法参数
Outer$1(Outer paramOuter, char paramChar, Integer paramInteger)
{
super(paramOuter);
}
void innerTest()
{
System.out.println(this.this$0.string);
System.out.println(this.val$ch);
System.out.println(this.val$integer);
}
}
3. 使用final修饰的答案 3.1 为什么外部类成员变量不需要final修饰
因为非静态内部类保存了外部类对象的引用,所以内部类对外部类成员变量的修改实际上会反映外部类实例本身,所以不需要添加final修饰。
3.2 为什么局部变量需要加final修饰
因为局部变量是匿名内部类的成员变量,所以在内部类中对变量的修改不会影响到外部类的外部方法。
所以,一刀切,只用最后的修改。 即保证内部类和外部类变量的一致性。