2017-01-23 8 views
1

私は次のHashMapを持っています。その目的は、JPanelを拡張するクラスの特定のメソッドを呼び出すために使用されることです。メソッドは、HashMapの値であり、渡されたパラメータはキーです。Javaリフレクションは匿名クラスの元のインターフェイスを取得

HashMap<Object, String> methodMapper = new HashMap<>(); 

projectMethodMapper.put("Some title", "setInfoTitle"); 

projectMethodMapper.put(new ActionListener() { 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     System.out.println("working"); 
    } 
}, "attachListener"); 

この特定のHashMapは、InfoPanelというクラスに使用され、以下のメソッドがあります。

public void attachListener(ActionListener al) { 
    this.button.addActionListener(al); 
} 

public void setInfoTitle(String name) { 
    ((TitledBorder) this.getBorder()).setTitle(name); 
} 

その後、私はHashMapのキーを反復します。

InfoPanel infoPanel = new InfoPanel(); 

for (Object key : keys) { 
    Method method = InfoPanel.class.getDeclaredMethod(methodMapper.get(key), key.getClass()); 

    method.invoke(infoPanel, key)); 
} 

あなたが想像できるように、キーはStringオブジェクトであるとき.getClassがMainPanel $ 1を返して、それは匿名だからgetDeclaredMethodがタイプMainPanel $ 1のパラメータを持つメソッドattachListenerを検索するとき、問題が来る問題はありませんクラスはオンザフライで作成されました。私の質問は - どのようなインターフェイスは、オブジェクトのインスタンス化に使用される匿名クラスの作成に使用されて見つけるのですか?

答えて

1

あなたの質問

に簡単な答えは、どのように私は、オブジェクトのインスタンス化に使用する匿名クラスの作成に使用されているものインタフェース見つけるのですか?

は、次のコードスニペットに記載されています。しかし、あなたのアプローチが非常に問題になる可能性があることに注意してください。可能であれば、おそらくリファクタリングを試みるべきです。

public class Main { 
    private static Class<?> getDeclaredInterface(Object object) { 
     if (object == null) { 
      throw new NullPointerException(); 
     } 
     Class<?> objectClass = object.getClass(); 
     Class<?>[] implementedInterfaces = objectClass.getInterfaces(); 
     if (implementedInterfaces.length == 0) { 
      throw new IllegalArgumentException(objectClass.getSimpleName() + " implements no interfaces."); 
     } 
     if (implementedInterfaces.length > 1) { 
      throw new IllegalArgumentException(objectClass.getSimpleName() + " implements multiple interfaces."); 
     } 
     return implementedInterfaces[0]; 
    } 

    public static void main(String... args) { 
     Object object = (Closeable)() -> System.out.println("No-op."); 
     System.out.println(getDeclaredInterface(object)); // prints 'interface java.io.Closeable' 
    } 
} 
0

これにはリフレクションを使用する必要はありません。もちろん

InfoPanel infoPanel = new InfoPanel(); 

commandList.forEach(command -> command.accept(infoPanel)); 

、このレバレッジ:あなたはInfoPanelを作成するとき、後に続いて

List<Consumer<InfoPanel>> commandList = new ArrayList<>(); 

commandList.add(panel -> 
    panel.attachListener(e -> System.out.println("working")) // using lambda for brievety 
); 

commandList.add(panel -> panel.setInfoTitle("Some Title")); 

:あなたは、それぞれの引数としてInfoPanelを取るファンクタのリストがbasciallyあるList<Cosumer<InfoPanel>>、使用することができますJava8が必要ですが、必要に応じてJava7でも同じことが可能です。


あなたはリフレクションを使用して主張する場合、あなたが期待されるパラメータの型を格納したデータ型と同様に、メソッド名と引数を作成することができます。

class Signature { 
    private final String name; 
    private final Class<?>[] parameters; 
    private final Object[] arguments; 

    ... 
} 

は、そのリストを持っている:

後に続いて
List<Signature> signatures = ...; 

signatures.add(new Signature("attachListener", 
    new Class<?>[] { ActionListener.class }, 
    new Object[] { e -> System.out.println("working") })); 

、検索のためにそのパラメータリストを使用します。

InfoPanel infoPanel = new InfoPanel(); 

for(Signature s : signatures) { 
    Method m = InfoPanel.class.getDeclaredMethods(s.getName(), s.getParameters()); 

    m.invoke(infoPanel, s.getArguments()); 
} 
+0

反射の使用は交渉可能ではありません。この例は、問題の内容を示すために非常に単純化されています。 InfoPanelは厳密にはInfoPanelではなく、多くのクラスの1つで、HashMapの反復処理の瞬間には、実際にどのクラスが使用されているのかを制御することはできないため、List >を作成することはできません。反射を伴って起こらなければならない、代替は不可能である。しかし、私はそれが将来他の誰かに役立つことを願っています。 :) –

+0

@HristoValchevHristovしかし、オブジェクトが厳密に 'InfoPanel'でない場合、how/whyメソッドの' attachListener'と 'setInfoTitle'メソッドを呼び出していますか?これらの呼び出しは、オブジェクトに実際にそれらのメソッドがある場合にのみ機能します。それらがスーパータイプの 'InfoPanel'に属していれば、代わりにそのスーパータイプのコンシューマを使うことができます。私はまだあなたがリフレクションを使用する理由を理解していません。 –

+0

短いストーリー:存在しなければ私は彼らに電話していません。複雑な答えがあり、実際には問題とは関係ありません。問題は、ActionListenerオブジェクトを受け取るメソッドが見つからないことです。 –

関連する問題