还有一个原因;考虑以下 java 程序:-
package example;
import java.io.Serializable;
import java.util.Arrays;
public class Test {
public static interface MyInterface {
void foo();
}
public static class BaseClass implements MyInterface, Cloneable, Serializable {
@Override
public void foo() {
System.out.println("BaseClass.foo");
}
}
public static class Class1 extends BaseClass {
@Override
public void foo() {
super.foo();
System.out.println("Class1.foo");
}
}
static class Class2 extends BaseClass implements MyInterface, Cloneable,
Serializable {
@Override
public void foo() {
super.foo();
System.out.println("Class2.foo");
}
}
public static void main(String[] args) {
showInterfacesFor(BaseClass.class);
showInterfacesFor(Class1.class);
showInterfacesFor(Class2.class);
}
private static void showInterfacesFor(Class<?> clazz) {
System.out.printf("%s --> %s\n", clazz, Arrays.toString(clazz
.getInterfaces()));
}
}
输出以下文本(java 6u16):
class example.Test$BaseClass --> [interface example.Test$MyInterface, interface java.lang.Cloneable, interface java.io.Serializable]
class example.Test$Class1 --> []
class example.Test$Class2 --> [interface example.Test$MyInterface, interface java.lang.Cloneable, interface java.io.Serializable]
注意 Class1 没有定义显式接口,因此 Class#getInterfaces() 不包含这些接口,而 Class2 包含。 this 的使用只有在这个程序中才变得清楚:-
package example;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import example.Test.BaseClass;
import example.Test.Class1;
import example.Test.Class2;
public class Test2 extends Test {
public static void main(String[] args) {
MyInterface c1 = new Class1();
MyInterface c2 = new Class2();
// Note the order...
MyInterface proxy2 = createProxy(c2);
proxy2.foo();
// This fails with an unchecked exception
MyInterface proxy1 = createProxy(c1);
proxy1.foo();
}
private static <T> T createProxy(final T obj) {
final InvocationHandler handler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.printf("About to call %s() on %s\n", method
.getName(), obj);
return method.invoke(obj, args);
}
};
return (T) Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj
.getClass().getInterfaces(), handler);
}
}
哪些输出:-
About to call foo() on example.Test$Class2@578ceb
BaseClass.foo
Class2.foo
Exception in thread "main" java.lang.ClassCastException: $Proxy1 cannot be cast to example.Test$MyInterface
at example.Test2.main(Test2.java:23)
虽然 Class1 确实隐式实现了 MyInterface,但创建的代理没有。
因此,如果我们想要创建一个动态代理,它为具有隐式接口继承的对象实现所有接口,那么一般来说,唯一的方法是将超类一直返回到 java.lang.Object,如以及遍历所有已实现的接口及其超类(请记住 Java 支持多个接口继承),这听起来效率不高,但显式命名接口要容易得多(而且更快),因为我认为它们是在编译时设置的.
那么什么使用反射和代理呢?一个 RMI...
因此,是的,这是一种方便,但不,它肯定不是多余的:请记住,这些类是由 Josh Bloch 精心设计和实现的,所以我怀疑它们是以这种方式显式编程的,以便代理网络存根和骨架工作和他们一样。