通过反射,我们可以获得一个类运行时的信息(属性,构造方法和普通方法),但是当我们是使用反射区获取一个类的内部类的构造方法时,会发现内部类默认的无参构造中会出现父类类型的参数
测试代码:
public class OuterClass {
class InnerClass{
}
}
注意:Class.forName()中的类名不能使用eclipse中的Copy qualified Name 来获取,应为内部类编译后会产生两个文件,具体做法是:到工程的根目录下,找到bin文件夹,java文件编译后的calss文件都放在这个目录下,找到编译后的内部类的class文件,复制类名,然后在前面加上包名即可
import java.lang.reflect.Constructor;
public class Test {
public static void main(String[] args) {
try {
Class clazz=Class.forName("reflect.OuterClass$InnerClass");
Constructor[] constructors = clazz.getDeclaredConstructors();
for(Constructor c:constructors){
System.out.println(c);
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
结果:
使用反射获取内部类的构造方法时,获取的并不时它的无参构造,而是带有父类类型的参数,具体原因如下
编译后的文件:
编译后产生了三个文件,外部类中的内部类编译后会产生一个 外部类类名$内部类类名.calss的文件
使用javap反编译命令对这两个文件进行反编译
OuterClass.class
OuterClass$InnerClass.class
可以看到,外部类中有一个public reflect.OuterClass的无参构造
在看内部类,是一个final reflect.OuterClass this$0 和 reflect.OuterClass$InnerClass(reflect.OuterClasss)的构造函数
对于这个貌似无法从JDK中查看原因,就来阐述一下我的理解,又不对的地方还望指教
对于final reflect.OuterClass this$0 我个人认为,内部类在编译后会与外部类分离,这个final类的的reflect.OuterClass类型的变量this$0 应该是一个与外部类建立联系的表示,而reflect.OuterClass$InnerClass(reflect.OuterClasss)可以从创建外部类的创建入手如果想要在外部类的外部获得内部类的对象,需要进行如下声明:OuterClass.InnerClass innerClass=new OuterClass().new InnerClass() ,可以看出,想要获得内部类对象需要先new OuterClass(),然后再new InnerClass(),在可以获得一个内部类的对象,这也就就是了为甚麽获得一个内部类需要先new出一个外部类,因为内部类中的默认构造中有一个外部类类型的参数
验证:
static关键字可以用于修饰变量和方法,代码块等,不能修饰再类上,但是并不是绝对的,static关键字是可以修饰内部类,且用static关键字修饰的内部类和不同内部类也有很大的不同
static关键字修饰内部类
代码:
public class OuterClass {
static class InnerClass{
}
}
静态内部类(InnerClass)意味着创建一个static内部类的对象,不需要一个外部类对象,不能从一个static内部类的一个对象访问一个外部类对象
测试代码:
public class Main {
public static void main(String[] args) {
InnerClass in1 = new InnerClass();
//或
OuterClass.InnerClass in2 = new OuterClass.InnerClass();
}
}
使用以上两种方式都可以获得内部类的实例,但什么可以这样写?
对其进行反编译:
OuterClass$InnerClass.class
反编译之后,外部类并没有什么太大变化,但是内部类和之前有明显的差别
final reflect.OuterClass this$0 已经没有了,而且reflect.OuterClass$InnerClass(reflect.OuterClasss)也变成了reflect.OuterClass$InnerClass(),reflect.OuterClasss类型的参数已经没有了,
而此时可以用InnerClass in1 = new InnerClass();对其进行实例化,比没有依赖于外部类
OuterClass.InnerClass in2 = new OuterClass.InnerClass();也并没有先new OuterClass()这一操作
这也就验证了上面我的猜想
对于final reflect.OuterClass this$0 ,内部类在编译后会与外部类分离,这个final类的的reflect.OuterClass类型的变量this$0 应该是一个与外部类建立联系的表示,而reflect.OuterClass$InnerClass(reflect.OuterClasss)可以从创建外部类的创建入手,如果想要在外部类的外部获得内部类的对象,需要进行如下声明:OuterClass.InnerClass innerClass=new OuterClass().new InnerClass() ,可以看出,想要获得内部类对象需要先new OuterClass(),然后再new InnerClass(),在可以获得一个内部类的对象,这也就就是了为甚麽获得一个内部类需要先new出一个外部类,因为内部类中的默认构造中有一个外部类类型的参数