【问题标题】:Can you force a java object into implementing an interface at runtime?你能强制一个java对象在运行时实现一个接口吗?
【发布时间】:2011-03-05 01:21:19
【问题描述】:

现在我如下:

1) 一个 java 接口。

2) 一个具体的 java 类实现上述接口,但确实包含与接口中定义的每个方法匹配的方法签名。 p>

由于我无法更改第 2 项的实现,我想知道是否可以让一个接受第 1 项的实例作为参数的方法接受第 2 项而没有类转换异常。

感觉 Spring 中的各种编织/强制/AOP 机制应该可以实现这一点,但我不知道该怎么做。

有没有办法做到这一点?

【问题讨论】:

  • 不能只做一个实现接口并转发所有内容的包装器吗?
  • 有谁知道这种模式是否有一个名称(OP 想要什么),您将在其中将具有匹配签名的对象“投射”到接口上?

标签: java spring


【解决方案1】:

你能强制一个java对象在运行时实现一个接口吗?

是的,使用dynamic proxies 或字节码重写。但是,对我来说,您似乎正在寻找Adapter pattern

【讨论】:

  • 您是否有任何有关如何执行此操作的文档的链接,最好是声明式的?
  • @dskiles,使用代理,请参阅Java Dynamic Proxy - How reference concrete class。对于 AoP 方法,请查看 aspectjcglib 项目。
  • 适配器模式是要走的路,但有点疯狂的是,一种语言需要一个对象来显式地实现它会满足的所有接口。隐式接口肯定是要走的路,但这对 Java 程序员没有帮助。
【解决方案2】:

你不能让对象本身实现接口,但你可以使用Proxy之类的东西来创建一个实现接口的对象,并使用反射来调用原始对象上的适当成员。

当然,如果它只是一种接口类型和一种具体类型,你可以很容易地编写这样的包装器而不使用代理:

public class BarWrapper implements Foo
{
    private final Bar bar;

    public BarWrapper(Bar bar)
    {
        this.bar = bar;
    }

    public int someMethodInFoo()
    {
        return bar.someMethodInFoo();
    }

    // etc
}

【讨论】:

    【解决方案3】:

    这应该可以通过适配器解决。 定义另一个类来实现您的接口并委托给真实对象:

    class YourAdapter implements YourInterface {
    
        private final YourClass realObject;
    
        public YourAdapter(YourClass realObject) {
            this.realObject = realObject;
        }
    
        @Override
        public methodFromInterface() {
            // you said the class has the same method signatures although it doesn't
            // implement the interface, so this should work fine:
            realObject.methodFromInterface();
        }
    
        // .......
    
    }
    

    现在,给定一个需要YourInterface 的方法和一个YourClass 类型的对象:

    void someMethod(YourInterface param) {}
    
    void test() {
        YourClass object = getFromSomewhere();
        someMethod( YourAdapter(object) );
    }
    

    【讨论】:

    • 这就是我现在所拥有的,但我希望尽可能跳过适配器步骤。
    • 如果您不介意反思,您将需要使用其他一些答案中提到的代理方法。
    【解决方案4】:

    您可以使用Javassist 做您想做的事,方法是修改类的字节码或创建包装器/代理类。

    【讨论】:

      【解决方案5】:

      基本上有两种方式:

      a) 在您的对象周围编写一个装饰器,实现接口并委托给您的对象(这可以通过使用代理或编写一个简单的适配器类来完成)

      b) 改变字节码。 Spring AOP 的功能不足以做到这一点,但 AspectJ 编译器可以。这是一个单行:

      declare parents: YourClass implements YourInterface;
      

      由于您无权访问类源,您将不得不使用加载时间编织或编织库 jar。所有这些都在AspectJ in ActionRamnivas Laddad中得到了很好的解释

      【讨论】:

        猜你喜欢
        • 2010-12-30
        • 1970-01-01
        • 2012-10-02
        • 1970-01-01
        • 1970-01-01
        • 2019-08-12
        • 1970-01-01
        • 2016-12-09
        • 1970-01-01
        相关资源
        最近更新 更多