你能强制一个java对象在运行时实现一个接口吗?
现在我以下:
1)一个java接口。
2)一个具体的java类,它不实现上述接口,但包含一个方法签名,该签名匹配接口中定义的每个方法。
由于我无法更改第2项的实现,因此我想知道是否可以创建一个方法来接受第1项的实例作为参数接受第2项而没有类强制转换exception。
感觉就像Spring中的各种编织/强制/ AOP机制应该使这成为可能,但我不知道该怎么做。
有没有办法让这种情况发生?
你能强制一个java对象在运行时实现一个接口吗?
是的,使用动态代理或字节码重写。 但是,对我而言,您似乎正在寻找Adapter pattern
。
您无法使对象本身实现接口,但您可以使用Proxy之类的东西来创建实现接口的对象,并使用reflection来调用原始对象上的相应成员。
当然,如果它只是一种接口类型和一种具体类型,您可以轻松编写这样的包装器而不使用代理:
public class BarWrapper implements Foo { private final Bar bar; public BarWrapper(Bar bar) { this.bar = bar; } public int someMethodInFoo() { return bar.someMethodInFoo(); } // etc }
这应该可以通过适配器解决。 定义了另一个实现接口并委托给真实对象的类:
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) ); }
您可以通过修改类的字节码或创建包装器/代理类来完成Javassist所需的操作。
基本上有两种方法:
a)在你的Object周围编写一个装饰器来实现接口并委托给你的对象(这可以通过使用代理或编写一个简单的适配器类来完成)
b)更改字节代码。 Spring AOP不够强大,但是AspectJ编译器是。 这是一个单行:
declare parents: YourClass implements YourInterface;
由于您无权访问类源,因此您必须使用“加载时间编织”或编织库jar。 所有这些都在 Ramnivas Laddad的 AspectJ in Action中得到了很好的解释