ArrayList既然继承自AbstractList抽象类,而AbstractList已经实现了List接口,那么ArrayList类为何还要再实现List接口呢?

原文地址
https://www.cnblogs.com/bluejavababy/p/4320545.html
如有侵权,请联系删除,谢谢

首先请看下面这段代码:

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()));
 }
}

输出的结果为:

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\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实现接口代理时,就会报异常。

因此,这并不是一个错误,很可能是作者Josh Bloch为了便于实现代理而精心设计的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值