如果您知道要公开的 API 集,例如您知道要访问长度方法和迭代器方法,则可以定义一个接口:
public interface TheInterfaceIWant {
int length();
void quack();
}
并且您希望能够使用此接口访问未实现此接口的实例上的相应方法,您可以使用代理类:http: //download.oracle.com/javase/1.4.2/docs/api/java /lang/reflect/Proxy.html
所以你创建一个代理
final Object aDuck = ...;
TheInterfaceIWant aDuckWrapper = (TheInterfaceIWant) Proxy.newProxyInstance(
TheInterfaceIWant.class.getClassLoader(),
new Class[] { TheInterfaceIWant.class },
new InvocationHandler() {
public Object invoke(
Object proxy, Method method, Object[] args)
throws Throwable {
return aDuck.getClass().getMethod(
method.getName(), method.getParameterTypes()).invoke(aDuck, args);
}
});
然后,您可以像使用动态类型语言中的鸭子一样使用包装器。
if (aDuckWrapper.length() > 0) {
aDuckWrapper.quack();
}
这是一个完整的可运行示例,它使用包装器打印四次“Quack”:
import java.lang.reflect.*;
public class Duck {
// The interface we use to access the duck typed object.
public interface TheInterfaceIWant {
int length();
void quack();
}
// The underlying instance that does not implement TheInterfaceIWant!
static final class Foo {
public int length() { return 4; }
public void quack() { System.out.println("Quack"); }
}
public static void main(String[] args) throws Exception {
// Create an instance but cast away all useful type info.
final Object aDuck = new Foo();
TheInterfaceIWant aDuckWrapper = (TheInterfaceIWant) Proxy.newProxyInstance(
TheInterfaceIWant.class.getClassLoader(),
new Class[] { TheInterfaceIWant.class },
new InvocationHandler() {
public Object invoke(
Object proxy, Method method, Object[] args)
throws Throwable {
return aDuck.getClass().getMethod(
method.getName(), method.getParameterTypes()).invoke(aDuck, args);
}
});
for (int n = aDuckWrapper.length(); --n >= 0;) {
// Calling aDuck.quack() here would be invalid since its an Object.
aDuckWrapper.quack();
}
}
}