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