我试图在我的eclipse工作区的java.lang包中创建一个自定义的类字符串。 起初我怀疑,在同一个包一个相同的类不能被创建,但我绝对惊讶我能在同一个包来创建一个类(字符串),即java.lang中自定义字符串类的创建
现在我很困惑
1)为什么是否有可能,并且
2)如果允许,可能是什么原因。
3)如果在Java中允许这种类型的Java类创建,会有什么用处。
我试图在我的eclipse工作区的java.lang包中创建一个自定义的类字符串。 起初我怀疑,在同一个包一个相同的类不能被创建,但我绝对惊讶我能在同一个包来创建一个类(字符串),即java.lang中自定义字符串类的创建
现在我很困惑
1)为什么是否有可能,并且
2)如果允许,可能是什么原因。
3)如果在Java中允许这种类型的Java类创建,会有什么用处。
您可以在java.lang包中创建一个新的类。如果禁止Oracle开发人员如何能够开发Java?我确定他们使用和我们一样的javac。
但是您将无法加载它,因为java.lang。类加载器(任何类加载器扩展)不允许这样做,每一个被加载的类经过该检查
...
if ((name != null) && name.startsWith("java.")) {
throw new SecurityException
("Prohibited package name: " + name.substring(0, name.lastIndexOf('.')));
}
...
所以你会在什么落得像
Exception in thread "main" java.lang.SecurityException: Prohibited package name: java.lang
at java.lang.ClassLoader.preDefineClass(ClassLoader.java:649)
at java.lang.ClassLoader.defineClass(ClassLoader.java:785)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
at Test1.main(Test1.java:11)
至于那黑影现有的类象类你的java.lang.String
它们不能被加载,因为System ClassLoader(默认的)使用“父第一”策略,所以java.lang类将通过引导类加载器从rt.jar加载。所以你需要用你的版本替换rt.jar中的String.class。或覆盖它使用-Xbootclasspath/p:
java选项,其中preprends路径引导类加载器搜索路径。所以,你可以
1)copypaste真正String.java内容到您的String.java
2)改变的方法,例如
public static String valueOf(double d) {
return "Hi";
}
和编译String.java
3)创建一个测试类
public class Test1 {
public static void main(String[] args) throws Exception {
System.out.println(String.valueOf(1.0d));
}
}
4)运行它为
java -Xbootclasspath/p:path_to_your_classes Test1
,你会看到
Hi
此答案如何回答OP指出的3个问题? – SpaceTrucker
是的,您可以创建名称为java.lang的包以及名为的字符串字符串。
但是你不能运行你的String类。
1)为什么有可能:编译器会成功编译你的类。
2)如果允许,可能是什么原因:您的包和类有一个有效的名称,所以编译器不会发出抱怨。
3)如果在Java中允许创建Java类的这种类型,那么会有什么用处:但是这个String类没有太多用处。 Bootstrap类加载器将从sun的java.lang包加载类。所以你的自定义字符串类将不会被加载,因此它在运行时会失败。
引导类加载器是JVM实现的一部分,它加载了Java API类(包括java.lang.String)。同样对于每个被加载的类,JVM都会跟踪哪个类加载器是引导程序还是用户定义的 - 加载类。因此,加载自定义String类的任何尝试都将失败,因为String类已被加载。
你应该解释他为什么不能跑步。 – SpaceTrucker
我想我已经解释了... –
感谢rai.sKumar,如果我有两个选择答案的选择,我会明确选择这个作为第二个最佳答案。因为它很清楚,准确而且重要。但Evgeniy Dorofeev所选择的答案是这样的(即使是代码),即使是外行人也能理解和模拟问题,所以牢记这一点,我选择了他的答案作为接受的答案,但无论如何非常非常感谢:) –
这被称为类阴影。
1.)这是可能的,因为Java类不是静态链接的,而是在类加载时链接的。
2.)如果不允许的话,那么整个类的加载会更难实现。然后,例如,您还必须针对特定的Java版本构建项目。因为Java类可能会因版本而异。这不会是一个可维护的方法。
3.)osgi利用它可以加载相同包的不同版本。另一个常见的用例是替换框架中的buggy类,其中没有其他解决方法是可能的。但是,应该谨慎使用这种技术,因为错误可能很难调试。
请注意,不能在java。*包中使用影子类,因为这会破坏Java安全沙箱。所以你会在运行时遇到问题。
如果记错,所述'java.lang'包[密封(http://docs.oracle.com/javase/6/docs/technotes/指南/扩展/ spec.html#密封),所以你不能添加成员。如果在运行时jar中替换String类型而不在运行时jar中取得成功,我会感到惊讶,因为该类型对于JVM的操作有多基础。 – McDowell