5

プライベート内部クラス内に存在するプライベート メソッドをテストしたい

 public class MyBigClass {
    private class MyInnerClass {
       private void wantedMethod() {
       }
    }
 }

を呼び出しwantedMethod() てテストしたい

これが私のコードです

Class[] classes = MyBigClass.class.getDeclaredClasses();
    for (int i = 0; i < classes.length; i++) {
        // this code print "MyInnerClass"
        System.out.println(">> inner classes >> " + classes[i].getSimpleName());
        if (classes[i].getSimpleName().equals("MyInnerClass")) {
            Class clazz = classes[i];
            // Constructor c=clazz.getConstructor();
            Method[] methods = clazz.getDeclaredMethods();
            // this code print "wantedMethod"
            for (int j = 0; j < methods.length; j++) {
                System.out.println("inner class methods >>  " + methods[i].getName());
            }

        }

    }    

問題: 電話がかけられないwantedMethod()

4

2 に答える 2

6

非静的メソッドを呼び出したい場合は、呼び出したいオブジェクトを指定する必要があります。あなたの場合、内部クラスオブジェクトが必要ですが、まだ持っていないので作成する必要があります。Java では、外部クラス オブジェクトなしでは内部クラス オブジェクトを作成できないため、その外部オブジェクトも作成する必要があります。

したがって、次の手順を実行する必要があります。

  • 外側のクラス オブジェクトを作成します (ない場合)。
  • 外部クラス オブジェクトを使用して内部クラス オブジェクトを作成し、
  • 内部クラス オブジェクトのメソッドを呼び出します。

次のように実行できます:
(デフォルトのコンストラクターはそのクラスの可視性と同じ可視性を持っていることを覚えておく必要があります。そのため、プライベート クラスにはプライベート コンストラクターがあり、使用する前にアクセス可能にする必要があります)

try {
    //creating parent object
    Object outer = new MyBigClass();

    //creating inner class object
    Class<?> innerClass = Class.forName("MyBigClass$MyInnerClass");
    Constructor<?> constructor = innerClass.getDeclaredConstructor(MyBigClass.class);//inner object must know type of outer class
    constructor.setAccessible(true);//private inner class has private default constructor
    Object child = constructor.newInstance(outer);//inner object must know about its outer object

    //invoking method on inner class object
    Method method = innerClass.getDeclaredMethod("wantedMethod",new Class<?>[]{});
    method.setAccessible(true);//in case of unaccessible method
    method.invoke(child,new Object[]{});

} catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
}

リフレクションを介して内部クラス オブジェクトを作成する方法の詳細については、この質問を参照してください。

于 2012-05-16T15:41:12.510 に答える
2

これは、クラスに名前が付けられていないためCodeCircuitです。ifその条件を削除すると、機能します。

Constructor c=clazz.getConstructor();例外がスローされるため、行も削除します。

これらの変更を行った後、独自のコードが出力されます

>> inner classes >> MyInnerClass
inner class methods >>  wantedMethod

編集

このコードを使用してメソッドを実行します。

    Class<?>[] classes = MyBigClass.class.getDeclaredClasses();

    for (Class<?> clazz : classes) {
        if(clazz.getSimpleName().equals("MyInnerClass")) {
            Method method = clazz.getDeclaredMethod("wantedMethod", new Class[] {});
            method.setAccessible(true);
            method.invoke(clazz.getDeclaredConstructor(MyBigClass.class).newInstance(new MyBigClass()), new Object[] {});
        }
    }

構文は少し奇妙で、内部クラスのコンストラクターを取得するために外部クラスを使用する必要があります。内部クラスで定義された以下のシグネチャを持つコンストラクターがあるかのように動作します。

public MyInnerClass(MyBigClass bigClass) {
}

しかし、それがJavaがリフレクションを使用して内部(ネストされた)クラスを処理する方法だと思います。

public内部クラスのコンストラクターを提供する必要があることに注意してください。

public class MyBigClass {
    private class MyInnerClass {
        public MyInnerClass() {
            System.out.println("hello");
        }
        private void wantedMethod() {
            System.out.println("world");
        }
    }
}

またsetAccessible(true)、プライベート メソッドを呼び出せるようにする必要があります。

編集2

さらに調査して、生成されたMyBigClass$MyInnerClass.classクラスを逆コンパイルしたところ、私の勘が正しかったことがわかりました。

public class MyBigClass$MyInnerClass {
    public MyBigClass$MyInnerClass(MyBigClass paramMyBigClass) {
        System.out.println("hello");
    }
    private void wantedMethod() {
        System.out.println("world");
    }
}

誰かがこの行動に光を当てることができれば、本当にうれしいです

于 2012-05-16T11:34:27.127 に答える