[英]Java reflection get anonymous class' origin interface
我有以下 HashMap。 它的目的是用於調用擴展 JPanel 的類的某些方法。 方法是 HashMap 中的值,傳遞的參數是鍵。
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 對象時沒有問題,當 getDeclaredMethod 搜索具有 MainPanel$1 類型參數的方法 attachListener 時出現問題,因為 .getClass 返回 MainPanel$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'
}
}
您不需要為此使用反射。 您可以使用List<Cosumer<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
:
InfoPanel infoPanel = new InfoPanel();
commandList.forEach(command -> command.accept(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());
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.