我在包Object
中创建了一个名为java.lang
的类。在另一个包中,我创建了Main
类。现在在Main类的main方法中,当我写new Main()
并在其后放一个点时,我没有看到equals()
,wait()
等等。即实际Object类的方法。
我的问题是你不认为不应该允许创建一个名为Object的类(特别是使用java.lang包)。因为Object类默认是由所有类继承的,所以在我的情况下,我定义的任何类都将自动继承我的类而不是实际的对象类,因为我的对象类的类名和包名与实际对象类的类名相同。
答案 0 :(得分:3)
这是一个非常开放的问题。
是否应该允许?为什么不,如果你知道你在做什么,那就疯了。
我同意这在理论上有些危险,但我不知道有人会错误地做到这一点。如果有人因某种原因想要重新定义整个Object类,例如学术界,那么他/她可以自己承担风险。
没有任何语言可以完全阻止您将箭射入自己的膝盖。
答案 1 :(得分:0)
我可以确认,即使你写了一个它也不会有用(至少使用通常的java类加载)java.lang中的那些优先级,因为它们已经被系统类加载器加载,你的Object类永远不会被选中并调用任何自定义方法只会导致运行时错误(java.lang.NoSuchMethodError)
但是当我使用自定义类加载器并覆盖其loadClass方法时,我不确定这种行为,以便它显式加载您的类字节但不在父类加载器中进行查找。可能是家庭工作:))
答案 2 :(得分:0)
我使用这个技巧(在我们的类路径中有一些第三方相同的包和类名)经常覆盖第三方库的功能,如果我不能将它们包装起来。
无论如何,在加载客户端程序(我们的应用程序)之前,必须将所有系统类加载到jvm中。这一切都是为了处理ClassLoader
,编译器允许它,因为它实际上并不关心所有类,但是在运行时,JVM类加载器会考虑这些事情,如果你看一下源代码默认ClassLoader
(oracle jdk),您可以看到将检查您是否应该使用java.
private ProtectionDomain preDefineClass(String name,
ProtectionDomain protectionDomain)
{
...
if ((name != null) && name.startsWith("java.")) {
throw new SecurityException("Prohibited package name: " +
name.substring(0, name.lastIndexOf('.')));
}
...
}
即使使用着名的咬合代码,javaassist
等工具也会限制这种行为,他们会检查是否可以检测课程Instrumentation.isModifiableClass
。
最后,这一切都取决于ClassLoader
实现,因为它必须遵守规范,您需要考虑从类路径到类的类的顺序。