在加载引用其他在运行时不可用的类的类文件时,我有一个非常奇怪的Java类路径行为。
加载一个具有(在运行时未触及的方法)的类,该类调用另一个类的构造函数,该类具有一个参数,该参数被转换为继承参数类的类,如果只引用了参数类的类未找到异常要加载的类,但该类的方法中没有引用的其他类在类路径中。
我正在使用以下java:
java version "1.6.0_18"
Java(TM) SE Runtime Environment (build 1.6.0_18-b07)
Java HotSpot(TM) 64-Bit Server VM (build 16.0-b13, mixed mode)
(Windows Server 2008 R2)
以下是一个示例:
public class A
{
public static void main(String[] args)
{
System.out.println("it works");
}
public void foo()
{
new B((D)null);
}
}
public class B
{
public B(C c) {
}
}
public class C
{
}
public class D extends C
{
}
现在我编译类,如果我在类路径中执行包含所有类文件的类A,它会产生“它工作”。
如果我从类路径中删除了除A类之外的所有类,则会发生以下错误:
Exception in thread "main" java.lang.NoClassDefFoundError: C
Caused by: java.lang.ClassNotFoundException: C
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
Could not find the main class: A. Program will exit.
尽管在运行时永远不需要C类。
以下星座作品(在A类中替换为“新B((D)null)”:
public class A
{
public static void main(String[] args)
{
System.out.println("it works");
}
public void foo()
{
D d = (D)null;
d.toString();
B b = (B)null;
b.toString();
new B(null);
}
}
public class B
{
public B(C c) {
}
}
public class C
{
}
public class D extends C
{
}
以下星座也有效(强制转换为C而不是D; C不继承任何类)
public class A
{
public static void main(String[] args)
{
System.out.println("it works");
}
public void foo()
{
new B((C)null);
}
}
public class B
{
public B(C c) {
}
}
public class C
{
}
public class D extends C
{
}
这是预期的行为还是Java错误?
答案 0 :(得分:1)
refer section 5.5,如果“如果运行时的值为null,则允许强制转换”,这就是为什么使用null转换工作。
答案 1 :(得分:0)
我还没有通过JSR,但我的猜测是,当解释器解释一个类文件时,它不会只执行所需的方法,它会完成所有操作。在这种情况下,需要A
,如果foo()
也被解释,则需要C
。所有这些都应该在加载A
时发生。所以错误..