実行時に利用できない他のクラスを参照するクラスファイルをロードするとき、非常に奇妙なJavaクラスパスの動作があります。奇妙なJavaクラスパス/クラスローダーの振る舞い
パラメータのクラスを継承するクラスにキャストされたパラメータを持つ別のクラスのコンストラクタを呼び出す(実行時に手を触れないメソッドを持つ)クラスをロードすると、クラスが見つかりませんif if paramter class ifロードするクラスのみが、そのクラスのメソッドで参照される他のクラスはクラスパスにありません。
私は次の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をexcepet削除する場合
は、次のエラーが発生します。クラスCは、実行時に必要とするべきではありません
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.
が。星座後
は(クラスAで置き換え、 "新B((D)ヌル)")作品:
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のバグですか?
「実行時にクラスCは決して必要ではありませんが、実行時には必ず必要です。 DはCなので、Cが必要ないと言うのは論理的に不可能です。 – Woot4Moo
これは当てはまりますが、Cに明示的にキャストしても実行時には利用できない場合は動作します。 クラスB、クラスC、クラスDは、mainメソッドはprintlnしか持たず、fooは決して呼び出されないように読み込まれるべきではありません。 – dominik
これはIDEかコマンドラインで行いますか?両方の環境で試してみてください。時にはEclipseが "役立つ"のが好きです。 – Woot4Moo