gpt4 book ai didi

java - 包本地类的 Class literal 和 Class.forName 的不同行为

转载 作者:行者123 更新时间:2023-11-29 08:00:46 25 4
gpt4 key购买 nike

仅作为示例让我们考虑类 ClassFileAssembler来自 sun.reflect包。

这个类是一个包本地类:

class ClassFileAssembler implements sun.reflect.ClassFileConstants {...

所以我们连它的名字都不能用ClassFileAssembler ,我们不能直接导入它 - 它会导致编译器错误。

但是我们可以创建一个名为 sun.reflect 的包在我们的项目中使用 ClassFileAssembler此包内部的名称 - Java 编译器会认为我们在 ClassFileAssembler 中的包。

如果是这样,为什么不尝试获取对类对象的引用,即 ClassFileAssembler.class

Class<ClassFileAssembler> classFileAssemblerClass = ClassFileAssembler.class;

意外地,此代码导致运行时错误:java.lang.IllegalAccessError: tried to access class sun.reflect.ClassFileAssembler from class sun.reflect.Test .

但是我们仍然能够得到 ClassFileAssembler类对象:

Class<ClassFileAssembler> aClass = (Class<ClassFileAssembler>)Class.forName("sun.reflect.ClassFileAssembler");

它工作正常并为我们提供了完整的类描述。


所以,问题是:

1) 技术之间有什么区别,如何实现Class.forName0检索对类对象的引用,以及如何 .class可以?

2) 为什么他们有如此不同的安全检查?

3) 保护的原因是什么.class以这种方式引用?

4) 这些技术使用不同的类加载器吗?

最佳答案

Class.forName 不关心类是否是本地包。只有在您尝试使用该类时才会检查访问权限。顺便说一句,如果您执行 setAccessible(true),则可以绕过这些访问限制。

Reflection 库允许您做许多在 Java 代码中做不到的事情。 Java 有关于您可以做什么和不能做什么的规则。例如您不能在构造函数之外或多次设置 final 字段。注意:JVM 没有这个限制,在运行时你可以使用反射来改变它。

这个类是包本地的原因是为了限制类对这个包之外的代码的访问。这并不意味着如果您真的尝试就无法访问它,但您不太可能在没有认真考虑的情况下访问它。例如当我在我的 IDE 中导入类时,它通常会建议来自 com.sun.* 的类,这不太可能是正确的选择。 (我的 IDE 可以设置为忽略这些,但我经常寻找一些我不想要的新包)

Reflections 可以这样做的原因是为了支持序列化等功能。使用序列化,您需要能够在序列化库的包之外序列化类并获取字段并在反序列化时重置它们。许多反转控制库也使用了反射,尽管我怀疑这不是他们在设计时想到的。

关于java - 包本地类的 Class literal 和 Class.forName 的不同行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14518669/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com