4

Object在 package 中创建了一个名为 name 的类java.lang。在另一个包中,我创建了Main类。现在在 Main 类的 main 方法中,当我编写new Main()并在之后放置一个点时,我看不到equals()wait()等等。即实际 Object 类的方法。

我的问题是你不认为创建一个名为 Object 的类(特别是 java.lang 包)是不允许的。由于 Object 类默认情况下由所有类继承,所以在我的情况下,我定义的任何类都会自动继承我的类而不是实际的对象类,因为我的对象类的类名和包名与实际对象类的相同。

4

3 回答 3

3

这是一个相当开放的问题。

应该允许吗?为什么不呢,如果你知道自己在做什么,那就发疯吧。

我同意这在理论上有点危险,但我不明白有人会如何错误地做到这一点。如果有人出于某种原因(例如学术原因)真的想重新定义整个 Object 类,那么他/她可以自行承担风险。

没有任何语言可以完全阻止您将箭射中自己的膝盖。

于 2012-08-16T12:06:16.370 回答
0

我可以确认,即使您编写一个它也不会有用(至少对于通常的 java 类加载) java.lang 中的那些具有优先权,因为它们已经由系统类加载器加载,并且您的 Object 类将永远不会被选中并调用任何自定义方法只会导致运行时错误(java.lang.NoSuchMethodError)

但是我不确定当您使用自定义类加载器并覆盖其 loadClass 方法时的行为,即它显式加载您的类字节但不在父类加载器中进行查找。可能是家庭作业:)

于 2012-08-16T12:32:45.260 回答
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实现,并且由于它必须遵守规范,您需要考虑从类路径到加载的类的顺序。

于 2012-08-16T13:37:01.457 回答