我不確定這是否可以用Java,但我試圖實現一個在編譯時不可用的接口**並將它作爲一個對象傳遞給另一個類的界面。比方說,我有這樣的接口:Java反射:實現接口並傳遞給另一個類
public interface MyInterface {
void onReceive(int i);
}
和其他類,如:
public void MyClass {
ArrayList<MyInterface> listenerList = new ArrayList<MyInterface>();
public void add(MyInterface m) {
listenerList.add(m);
}
}
如果他們可以在編譯的時候,我會用他們喜歡的:
blah = new MyInterface() {
public void onReceive(int i) {
System.out.println("BLAH");
}
}
MyClass mc = new MyClass();
myClass.add(blah);
我想知道是否有一種方法可以編寫與上面相同的代碼,前兩個類只在運行時纔可用。
提前致謝!
**我試圖從Android的ROM使用框架庫,但它是在達爾維克字節碼,所以我不能用它進行編譯。
UPDATE:下面是我用來測試溶液一些示例代碼:
文件A/IIMSListener.java
// Excerpt from decompiled class
public interface IIMSListener
{
void onReceive(int p0, int p1/*, IMSParameter p2*/);
}
文件A/IMSRemoteListenerStub.java
// Excerpt from decompiled class
import java.util.concurrent.*;
import java.util.*;
public class IMSRemoteListenerStub
{
public List<IIMSListener> mListenerList = new CopyOnWriteArrayList<IIMSListener>();
public boolean addListener(final IIMSListener iimsListener) {
if (iimsListener != null && !this.mListenerList.contains(iimsListener)) {
this.mListenerList.add(iimsListener);
return true;
}
return false;
}
public boolean removeListener(final IIMSListener iimsListener) {
if (iimsListener != null && this.mListenerList.contains(iimsListener)) {
this.mListenerList.remove(iimsListener);
return true;
}
return false;
}
}
文件b/test.java
impor t java.lang.reflect。 ; import java.util。;
public class test {
public static void main(String[] args) throws IllegalAccessException,
IllegalArgumentException,
InvocationTargetException,
NoSuchMethodException,
SecurityException,
ClassNotFoundException {
// Implement interface
Class<?> IIMSListener = Class.forName("IIMSListener");
Object listenerInstance = Proxy.newProxyInstance(IIMSListener.getClassLoader(), new Class<?>[]{IIMSListener}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(method.getName().equals("onReceive")){
System.out.println("ARGS: " + (Integer)args[0] + ", " + (Integer)args[1]);
return 1;
}
else return -1;
}
});
// Test
Method onReceive = listenerInstance.getClass().getDeclaredMethod("onReceive", new Class[] { int.class, int.class });
onReceive.invoke(listenerInstance, new Object[] { 1, 2 });
try {
// Pass to another class
Class IMSRemoteListenerStub = Class.forName("IMSRemoteListenerStub");
Constructor ctor = IMSRemoteListenerStub.getConstructor();
Object stubInstance = ctor.newInstance(new Object[] {});
Method addListener = stubInstance.getClass().getDeclaredMethod("addListener", new Class[] { IIMSListener });
addListener.invoke(stubInstance, new Object[] { listenerInstance });
// Test
Field mListenerList = IMSRemoteListenerStub.getField("mListenerList");
List<?> list = (List<?>)mListenerList.get(stubInstance);
onReceive.invoke(list.get(0), new Object[] { 3, 4 });
}
catch (InstantiationException e) {}
catch (NoSuchFieldException e) {}
}
}
執行:
$ cd b
$ CLASSPATH=".:../a" java test
ARGS: 1, 2
ARGS: 3, 4
難道永遠都會有相同的接口或接口會改變? –
如果您在編譯時不知道類型,則必須使用反射來獲取構造函數和方法的列表。然後你需要找到解決任何參數的方法,以便調用任何方法或構造函數。總而言之,不是一個簡單的任務。 您可以使用JDK代理來使用'InvocationHandler'生成接口實例,但如果沒有該類型或反射的變量,它將不會很有用。 –
@李光華英文名男子。 –