Java动态适配器

标签 java adapter

我正在使用一些生成以下接口(interface)的 Java 代码。此代码不可修改。

interface A1 {
    public void run();
}

interface A2 {
    public void run();
}

...

interface A24 {
    public void run();
}

我在使用以下代码时遇到类转换错误。我如何动态地构建一个适配器到我的界面?

interface ARunnable {
    public void run();
}

public void someMethod() {
    // getARunnables() returns a list of A1, A2, ... A24
    List<ARunnable> runnables = (List<ARunnable>)getARunnables(); 

    for (ARunnable a : runnables) {
        a.run();
    }
}

最佳答案

由于无法修改接口(interface)来扩展 java.lang.Runnable,因此可以选择使用 java.lang.reflect.Proxy 来构建委托(delegate)给 A1、A2... 接口(interface)的 Runnable 实例。

这并不简单,但请看一下使用 java.lang.reflect.Proxy 的示例。该示例只是根据方法名称委托(delegate)给委托(delegate)对象。

public class ProxyTest
{
    public static void main(String... args)
    {
        List<?> instances = Arrays.asList(new A1());
        List<ARunnable> runnableInstances = new ArrayList<ARunnable>(instances.size());
        for (Object instance : instances)
        {
            ARunnable runnableInstance = (ARunnable)Proxy.newProxyInstance(
                                            ARunnable.class.getClassLoader(), 
                                            new Class<?>[] {ARunnable.class}, 
                                            new RunnableWrapper(instance));
            runnableInstances.add(runnableInstance);
        }

        //Now we have a list of ARunnables!
        //Use them for something
        for (ARunnable runnableInstance : runnableInstances)
        {
            runnableInstance.run();
        }
    }

    private static class RunnableWrapper implements InvocationHandler
    {
        private final Object instance;

        public RunnableWrapper(Object instance)
        {
            this.instance = instance;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable
        {
            //Ensure that your methods match exactly or you'll get NoSuchMethodExceptions here
            Method delegateMethod = instance.getClass().getMethod(method.getName(), method.getParameterTypes());
            return(delegateMethod.invoke(instance, args));
        }
    }

    public static class A1
    {
        public void run()
        {
            System.out.println("Something");
        }
    }

    public static interface ARunnable
    {
        public void run();
    }
}

我还建议你修复线路

List<ARunnable> runnables = (List<ARunnable>)getARunnables(); 

您不应忽视这种类型的安全警告。该对象列表实际上并不包含 ARunnables,因此会出现 ClassCastException。

关于Java动态适配器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6463027/

相关文章:

android - 如何在 android 中为列表适配器使用 Notifydatasetchanged

android - 适配器第一个位置 = 第 6 个位置?

android - ListView 内的 ImageButton onClick()

java - 从 ArrayList 中删除重复的字符串

java - 在多个方法中分发 JDBC 事务的语句

java - 如何使用 Omnifaces 1.14.1 修复 javax.xml.xpath.XPathFactoryConfigurationException

java - 程序未创建文件。怎么了?

java - 从 Worklight 适配器调用 Java 类的 ECMA TypeError

android - 使用基本适配器和 ListView 显示来自 SQLite 的变量数据

java - 连字符预处理