关于匿名内部类的问题详解
之前写了篇关于内部类是如何访问外部类私有对象的在的角度就是成员内部类,详细的讲解了基本的原理
下面我开始讲解下有关匿名内部类的有关原理(ps:个人理解)。
public class OutClass{
private String name = "sa";
private int id = 12;
private String address = "jaxu";
public void fun(String parm) {
Thread thread = new Thread() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(OutClass.this.name);
System.out.println(parm);
System.out.println(Thread.currentThread().getName());
}
}
};
thread.start();
}
}
首先简单写个匿名内部类。 然后编译
生成两个class文件,然后通过反编译看看里面结果
和成员内部内部类一样,匿名内部类生成一个常量引用,指向外部类,而且因为我的匿名内部类中调用了外部类的成员方法,和方法参数,所以还生成了一个常量成员参数
var$parm,这个参数是怎么赋值进去的呢,通过匿名内部类中的构造方法,可以看出,里面有两个参数,一个是外部类的引用,一个是外部类的方法的参数的值。为什么需要外部类方法参数的值parm呢
首先我们来思考下,调用过程,首先外部类fun方法被调用,生成一个内部类对象,然后调用start方法,方法参数的生命周期结束,为了在内部类中使用该参数,编译器用一个副本在生成内部类对象的时候将这个参数保存下来!
然后我们在看下一个问题
匿名内部类的构造方法,匿名内部类是可以有构造方法的,但是你是无法自己手动写一个构造函数的,因为,匿名内部类没有名字,所以你无法手动写出来,但是编译器可以自动生成一个。
然后再看看参数问题,有些书上规定如果方法参数被匿名内部类调用,必须改成final,但是我这里没有用final编译器也没出问题啊,表面上看是这样,但是如果你在方法体里第一行改变parm引用所指向的值,那么就会报错,实际上这个参数是final,不管你写没写final,只要参数被内部类使用。
最后我们看下反编译情况下,外部类中fun方法做了什么事情
看到红线没,这里调用的构造方法是带有两个参数的,说明我们上面分析的没错。