Java更多的库谜题80:更深层的反射

Java更多的库谜题80:更深层的反射,第1张

Java更多的库谜题80:更深层的反射,第2张

下面的程序通过打印由反射创建的对象来产生输出。那么它会打印出什么呢?
公共类Outer{
公共静态void main(String[] args)引发异常{
new Outer()。greet world();
}

private void greetWorld()抛出异常{
system . out . println(inner . class . new instance());
}

public class Inner {
public String toString(){
返回“Hello world”;
}
}
}

这个程序似乎是最常见的Hello World程序的另一个特殊变体。Outer中的main方法创建一个外部实例,并调用它的greetWorld方法,该方法将反射创建的一个新的内部实例打印为一个字符串。Inner的toString方法总是返回标准的问候语,所以程序的输出应该像往常一样是Hello World。如果你试着运行这个程序,你会发现实际的输出更长更混乱:

线程“main”实例化异常异常:Outer$Inner
at Java . lang . class . new instance 0(class . Java:335)
at Java . lang . class . new instance(class . Java:303)
at Outer . greet world(Outer . Java:7)
at Outer . main(Outer . Java:3)

为什么会抛出这个异常?从5.0版本开始,关于Class.newInstance的文档规定:如果那个类对象“表示抽象类、接口、数组类、原语类型或者空(void);或者这个类没有任何空的[即无参数]构造函数;或者实例化因为某种其他原因失败,那么就会抛出异常“[JAVA-API]。这里的问题满足什么条件?不幸的是,异常消息没有提供任何提示。在这些条件中,只有最后两个可能得到满足:要么是外部条件。Inner没有空的构造函数,或者实例化因“某些其他原因”而失败。就像外层的情况一样。内部,当一个类没有任何显式构造函数时,Java会自动提供一个不带参数的公共默认构造函数[JLS 8.8.9],所以应该有空构造函数。但是,newInstance方法调用失败的原因是外部的。Inner没有空构造函数!

非静态嵌套类的构造函数在编译时会将一个隐藏参数作为它的第一个参数,这表示它的直接封闭实例[JLS 13.1]。当您在代码中编译器可以找到合适的外围实例的任何地方调用构造函数时,此参数将被隐式传入。但是,上面的过程只适用于普通的构造函数调用,也就是不使用反射的时候。当使用反射调用构造函数时,需要显式传递这个隐藏参数,这对于Class.newInstance方法是不可能的。传递这个隐藏参数的方法是使用java.lang.reflect.Constructor当程序被这样修改后,可以正常打印出Hello World:

private void greetWorld()抛出异常{
构造函数c = inner . class . get Constructor(outer . class);
system . out . println(c . new instance(outer . this));
}

或者,您可能已经观察到内部实例不需要外围外部实例,因此您可以将内部类型声明为静态。除非你真的需要一个外围实例,否则你应该使用静态成员类而不是非静态成员类[EJ第18条]。该程序可通过以下简单修改进行修订:

公共静态类内部{...}

Java程序的反射模型不同于它的语言模型。反映在虚拟机级别,暴露了大量从Java程序到类文件的翻译细节。这些细节中有一些是由Java语言规范管理的,但其余的可能会因不同的实现而有所不同。在Java语言的早期版本中,从Java程序到类文件的映射是直接的,但是随着一些虚拟机不能直接支持的高级语言特性的加入,例如嵌套类、协变返回类型、泛型和枚举,这种映射变得越来越复杂。

考虑到从Java程序到类文件映射的复杂性,避免使用反射来实例化内部类。一般来说,当我们在高级语言特性定义的程序元素上使用反射时,一定要小心。从反射的角度观察一个程序,可能和从代码的角度观察不同。请避免依赖不受语言规范管理的翻译细节。对于平台的实现者来说,这里的教训是重申,请提供清晰准确的诊断信息。

位律师回复
DABAN RP主题是一个优秀的主题,极致后台体验,无插件,集成会员系统
白度搜_经验知识百科全书 » Java更多的库谜题80:更深层的反射

0条评论

发表评论

提供最优质的资源集合

立即查看 了解详情