7

私はいくつかのクラスを持っていますA:

public class A {
    public A(String str) {
        System.out.println("Create A instance: " + str);
    }

    public void methodA() {
        System.out.println("#methodA1()");
    }
}

そして私のクラスローダーの実装:

public class MyClassLoader extends ClassLoader {
    public MyClassLoader() {    
        super();
    }

    @Override
    public synchronized Class<?> loadClass(String name) 
            throws ClassNotFoundException {

        System.out.println("Load: " + name);

        return super.loadClass(name);
    }
}

そして今、現在のスレッドでデフォルトのクラスローダーを変更しようとしています:

import java.util.ArrayList;
import java.util.List;

public class ChangeLoaderTest {
    public static void main(String[] args) {
        // Save class loader so that we can restore later.
        ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();

        MyClassLoader newLoader = new MyClassLoader();
        try {
            // Set new classloader.
            Thread.currentThread().setContextClassLoader(newLoader);

            // My class.
            A a = new A("1");
            a.methodA();

            // Standard Java class.
            List<Integer> list = new ArrayList<Integer>();
            list.add(2);
            list.add(3);
        } finally {
            // Restore.
            Thread.currentThread().setContextClassLoader(oldLoader);
        }
    }
}

そしてChangeLoaderTest出力:

Create A instance: 1
#methodA1()

誰も

Load: ...

なんで?どうすればClassLoaderいくつかのスレッドに変更できますか?

4

3 に答える 3

4

Marko Topolnik が指摘しているように、コンテキスト クラスローダーはフレームワークで使用するためのものです。自分でクラスローダーを使用するには、呼び出してからloadClass("somepackage.A")、リフレクション API を使用して A ( ) の新しいインスタンスを作成する必要がありますClass.newInstance()

呼び出し元のコードは A を認識しないため、ソースで A またはそのメソッドを直接使用することはできません。別のクラスローダーを使用します。通常のクラスローダーでロードできる A のインターフェースまたは基底クラスを使用して、リフレクションを回避できます。

interface AIF{
        void someMethod();
 }
class A implements AIF{
      public void someMethod(){}
 }


public void test(){
     MyLoader loader = new MyLoader();
     Class cla = loader.loadClass("A");
     AIF a = (AIF) cla.newInstance();
     a.someMethod();

 }
于 2012-04-17T14:23:00.930 に答える
3

このcontextClassLoaderメカニズムは、のような基本的なJava操作では使用されませんnew。そこにあるだけなので、さまざまなフレームワークが担当のコンテキストクラスローダーにアクセスして、リソースやクラスなどをロードできます。Javaは、実行中のコードをロードしたクラスローダーを常に使用します。それはあなたが経由してアクセスするものですChangeLoaderTest.class.getClassLoader()-そしてこれについてあなたができることは何もありません。

于 2012-04-17T13:58:40.870 に答える
0

何が起こるかというと、クラスローダーの「親」でもあるアプリケーションのクラスローダーがそれを見つけAてロードできるということだと思います。その結果、クラスローダーは検索されたり、ロードに使用されたりしませんA

正直なところ、私はクラスローダーの経験はあまりありませんが、クラスのパスにURLを使用するクラスローダーをサブクラス化した場合(クラスファイルを見つけることができるように)、親クラスローダーはそれをロードできません(クラスパスの一部ではありません)。 )、カスタムのものが使用されます。

于 2012-04-17T13:58:12.720 に答える