Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/xamarin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java反射:实现接口并传递给另一个类_Java_Android_Reflection_Interface_Dalvik - Fatal编程技术网

Java反射:实现接口并传递给另一个类

Java反射:实现接口并传递给另一个类,java,android,reflection,interface,dalvik,Java,Android,Reflection,Interface,Dalvik,我不确定这在Java中是否可行,但我正在尝试实现一个在编译时不可用的接口**,并将其作为该接口的对象传递给另一个类。假设我有一个界面,比如: public interface MyInterface { void onReceive(int i); } 还有另一类,比如: public void MyClass { ArrayList<MyInterface> listenerList = new ArrayList<MyInterface>();

我不确定这在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);
    }
}
我想知道如果前两个类只在运行时可用,是否有一种方法可以编写与上面相同的代码

提前谢谢

**我试图使用Android的ROM中的框架库,但它是dalvik字节码,所以我不能使用它进行编译

更新:下面是我用来测试解决方案的一些示例代码:

文件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;
    }
}

如果它将是相同的接口,那么使用

//在运行时加载类
公共静态void main(字符串[]args)抛出IllegaAccessException、IllegalArgumentException、InvocationTargetException、NoSuchMethodException、SecurityException、ClassNotFoundException{
Class someInterface=Class.forName(“someInterface”);
对象实例=Proxy.newProxyInstance(someInterface.getClassLoader(),新类[]{someInterface},新调用处理程序(){
@凌驾
公共对象调用(对象代理、方法、对象[]args)抛出Throwable{
//处理调用
if(method.getName().equals(“someMethod”)){
返回1;
}
否则返回-1;
}
}); 
System.out.println(instance.getClass().getDeclaredMethod(“someMethod”,“Class[])null.invoke(instance,new Object[]{}));
}

接口总是相同的还是会发生变化?如果在编译时不知道类型,则必须使用反射来获取构造函数和方法的列表。然后需要找到一种方法来解析任何参数,以便可以调用任何方法或构造函数。总而言之,这不是一项简单的任务。您可以使用JDK代理来生成带有
调用处理程序的接口实例,但如果没有这种类型的变量或反射,它将不会有多大用处。@Liuguanghua English man。谢谢您的回答!界面永远不会改变。我想知道的一件事是:如果
SomeInterface
在编译时不可用,它怎么能用作行的类型:
SomeInterface instance=…
?@ChenXiao Long哦,那是个错误。我编辑了答案,完全使用了反思。看一看。不过,这是一个很好的捕获。不过,我只是想知道如何插入正在加载的类以及您不知道的接口。我的意思是,你必须一直使用反射。为了提供更多的背景信息,我正在尝试从制造商的固件制作一个Android IMS协议库来与AOSP一起工作。我可以对库进行反编译以查看类和接口,从而查看我正在处理的函数。编辑:顺便说一句,您的解决方案非常有效!我将用我测试过的一些示例代码更新我的问题。所以在这种情况下,这会有所帮助。
// 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;
    }
}
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
//Loading the class at runtime
public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, ClassNotFoundException {
    Class<?> someInterface = Class.forName("SomeInterface");

    Object instance = Proxy.newProxyInstance(someInterface.getClassLoader(), new Class<?>[]{someInterface}, new InvocationHandler() {

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

            //Handle the invocations
            if(method.getName().equals("someMethod")){
                return 1;
            }
            else return -1;
        }
    }); 
    System.out.println(instance.getClass().getDeclaredMethod("someMethod", (Class<?>[])null).invoke(instance, new Object[]{}));
}