首先请看下面这段代码:
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 ", clazz, Arrays.toString(clazz .getInterfaces())); } }
输出的结果为:
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类的父类实现了接口,但是本身并没有再次实现接口,因此通过java.lang.Class直接获取Class1类的接口为空数组。
因此,在实现代理的时候就会出现问题,请看下面的代码:
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 ", 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实现接口代理时,就会报异常。
因此,这并不是一个错误,很可能是作者Josh Bloch为了便于实现代理而精心设计的。
参考:http://stackoverflow.com/questions/2165204/why-does-linkedhashsete-extend-hashsete-and-implement-sete