質問

リフレクションを使用して匿名の内部クラスのメンバーにアクセスする以外の方法はありますか?

役に立ちましたか?

解決

匿名内部クラスにはタイプがありますが、名前はありません。

名前付きスーパータイプで定義されていないフィールドにアクセスできます。ただし、名前付きの型変数に割り当てられると、インターフェイスは失われます。

明らかに、内部クラス自体からフィールドにアクセスできます。コードを追加する1つの方法は、インスタンス初期化子を使用することです:

final AtomicInteger y = new AtomicInteger();
new Runnable() {
    int x;
    {
        x = 5;
        doRun(this);
        y.set(x);
    }
    public void run() {
        ... blah ...
    }
};

匿名の内部クラス式によって返される値には匿名型があるため、クラス自体の外部で使用する機会が1つあります。

final int y = new Runnable() {
    int x;
    {
        x = 5;
        doRun(this);
    }
    public void run() {
        ... blah ...
    }
}.x;

次のように宣言されたメソッドを介して渡すこともできます。

<T extends Runnable> T doRun(T runnable);

他のヒント

匿名クラスの代わりにローカルクラスを使用できます。見て:

public class Test {
    public static void main(String... args) {
        class MyInner {
            private int value = 10;
        }

        MyInner inner = new MyInner();
        System.out.println(inner.value);
    }
}

ただし、メソッド本体でのみ MyInner 型の参照を持つことができます。そのため、メソッドの外部では、スーパークラス(この場合は java.lang.Object )またはインターフェイスで宣言されていないフィールド/メソッドを使用できません。


public class AccessAnonymous {
    private Runnable runnable; // to have instance of the class

    public static void main(String[] args) throws Exception {
        AccessAnonymous a = new AccessAnonymous();
        a.a(); // init field

        Class clazz = a.runnable.getClass();
        Field field = clazz.getDeclaredField("i");
        field.setAccessible(true);

        int int1 = field.getInt(a.runnable);
        System.out.println("int1=" + int1);
    }

    public void a() {
        runnable = new Runnable() {
            private int i = 1;

            public void run() {
                i = 90;
            }

        };
        runnable.run();// change value
    }
}

匿名クラスの場合、クラスに起因する混乱と匿名化の利便性の間にはトレードオフもあります。複雑なクラスはほとんど匿名ではなく、名前付きのprivate innerとして属します。

ほとんどの匿名クラスでは、「フィード」するだけで済みます。知識と建設時にそれを行うことができます。 いくつかの匿名クラス(戻り値のビークルなど)では、1つの戻り値も考慮します。

ご存知のように、データメンバーには直接アクセスするのではなく、ゲッターセッターを使用してアクセスする必要があります。これは、ゲッターとセッターをたくさん追加したという状況に陥った場合、とにかく何か間違ったことをしている可能性があり、匿名クラスを使用すべきではありません。

インターフェイスを実装するか、既存のクラスを拡張する場合、インターフェイスまたは基本クラスで定義されているメンバーにアクセスできます。

Mr Foozは正しいですが、インターフェイスは定数メンバーのみを定義できます。最良の方法は、ゲッター/セッターメソッドをインターフェイスに追加し、それらを使用して値を取得することです。しかし、その後、各匿名クラスに対して、それらのメソッドを定義する必要があります(苦痛の種)。

読みやすく保守可能なコードが必要な場合は、匿名クラスを使用しないでください。匿名クラスを使用しており、読み取り可能で保守可能なコードが必要な場合は、その内部クラスの要素にアクセスする必要があるときに匿名クラスを使用しないでください。そうする方法はありますが、これらのハッキングを使用しないようにお願いします。可読性は他のすべての美徳よりも優れています。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top