zoukankan      html  css  js  c++  java
  • ArrayList既然继承自AbstractList抽象类,而AbstractList已经实现了List接口,那么ArrayList类为何还要再实现List接口呢?

    首先请看下面这段代码:

    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

  • 相关阅读:
    ASP.NET常见安全缺陷集锦[转]
    林黛玉出家:给予中国给予我们的警示![摘]
    关于管理 关于经营 还有很多东西都无从做好
    ASP.NET 2.0的新增服务、控件与功能
    将可视的DataGrid、DataList等的规范表数据导出并写入xls或doc格式保存
    2006全球最具影响力品牌
    .NET环境下水晶报表使用总结[转]
    Asp.net(C#)分层——基础类
    Asp.Net传参方式小结
    MSN签名都成了广告位
  • 原文地址:https://www.cnblogs.com/bluejavababy/p/4320545.html
Copyright © 2011-2022 走看看