import java.io.*; class Instanceof { public static void main(String[] args) throws Exception { new Instanceof().test(); } public void test() throws Exception{ System.out.println(new Inner()); //1 System.out.println(Inner.class.newInstance()); //2 } public class Inner{ public String toString(){ return "Innser Object"; } } }
1处使用new方式来调用内部类的无参构造函数,2处使用反射来调用内部类的无参构造函数
运行时 在2处抛出异常:
Exception in thread "main" java.lang.InstantiationException: Instanceof$Inner
at java.lang.Class.newInstance0(Class.java:357)
at java.lang.Class.newInstance(Class.java:325)
at Instanceof.test(Instanceof.java:40)
at Instanceof.main(Instanceof.java:33)
都是调用无参构造函数怎么结果不一样呢?
使用javap -c Out.Inner 发现Inner内部类的构造函数有一个Instanceof 参数:
public class Instanceof$Inner { final Instanceof this$0; //① public Instanceof$Inner(Instanceof); //② Code: 0: aload_0 1: aload_1 2: putfield #1 // Field this$0:LInstanceof; 5: aload_0 6: invokespecial #2 // Method java/lang/Object."<init>": ()V 9: return public java.lang.String toString(); Code: 0: ldc #3 // String Innser Object 2: areturn }
看到了上面的① ②行就会明白了,其实,内部类的构造函数需要外部类的一个实例对象作为参数。因为非静态内部类是依赖于外部类的,所以需要一个外部类对象!对于1处,在new
Inner时,JVM 把 this 传给了 Inner的构造函数。而对于2处,通过反射技术调用Inner的无参构造函数却没有 外部类对象传给Inner构造函数所以抛出了异常。
class Instanceof extends Out.In { public static void main(String[] args) { System.out.println("In Instanceof"); } } class Out{ class In{ public void test(){ System.out.println("In In test"); } } class Child extends In{} }
上面代码编译错误,提示:
Instanceof.java:4: 错误: 需要包含Out.In的封闭实例
class Instanceof extends Out.In {
^
1 个错误
因为 在子类的构造函数中 会隐式调用父类的无参构造函数,而 Out.In 的无参构造函数其实需要一个Out对象作为参数,所以由于参数的不匹配,提示编译错误。
解决办法:
class Instanceof extends Out.In { public Instanceof(){ new Out().super(); } public static void main(String[] args) { System.out.println("In Instanceof"); } } class Out{ class In{ public void test(){ System.out.println("In In test"); } } class Child extends In{} }
在Instanceof类中写一个构造函数,在第一行 new出以Out对象,以该对象作为主调对象,显式调用Instanceof父类的构造函数即可。这样,就会将new出来的Out 对象传给In的构造函数。