【问题标题】:Java Collections Interface Dynamic DispatchJava 集合接口动态调度
【发布时间】:2021-01-22 13:10:33
【问题描述】:
Collection<Integer> list = new ArrayList<>();
list.add(0);
list.add(1);
list.add(2);

for (int i = 0; i < 3; i++) {
  list.remove(i);
}
System.out.println(list);
  }

}

我的问题: 为什么列表使用 remove(object o) 而不是 ArrayList.remove(int index)。我想在编译时,列出实际对象(动态类型)(Arraylist 的方法)而不是超类的方法。

【问题讨论】:

  • 这会执行remove(Object),因为您的list 变量是Collection 类型,而Collection 没有指定remove(int index) 方法。编译器只查看变量(Collection)的编译类型,而不是对象(ArrayList)的运行时类型。
  • 你自己没有注意到你的期望(编译时间动态类型)的矛盾吗?抛开在编译时使用动态(又名运行时)类型的技术问题:当编程语言总是使用运行时类型时,编译时变量类型的目的是什么?

标签: java inheritance collections interface


【解决方案1】:

这会执行remove(Object),因为您的list 变量是Collection 类型,而Collection 没有指定remove(int index) 方法。

编译器只查看变量的编译时类型 (Collection),而不是对象的运行时类型 (ArrayList)。

【讨论】:

  • 所以等等...因为静态类型是List。因为 list 中不存在 remove(int index),所以发生了自动装箱,所以它调用了 remove(object),所以编译器在 ArrayList 中查找 remove(object) 方法而不是 remove(int index) 版本,对吧?
  • 不知道你说的“静态类型是List”是什么意思。编译器在Collection 中寻找合适的方法,它找到的唯一方法是remove(Object)。所以它将int自动装箱为整数,是的。 ArrayList 中的 remove(int index) 方法不在考虑范围内。
【解决方案2】:

由于您的列表是 Collection 并且 Collection 没有 remove(int index) 但有 remove(Object o),因此删除是 remove(Object o)

当您将收藏更改为java.util.List 时,如下所示,删除类似remove(int index) 的作品。

List<Integer> list = new ArrayList<>();
list.add(0);
list.add(1);
list.add(2);

for (int i = 0; i < 3; i++) {
    list.remove(i); // IndexOutOfBoundsException expected though
}
System.out.println(list);

【讨论】:

    【解决方案3】:

    由于list被声明为Collection&lt;Integer&gt;,那么Collection的方法就会被调用。

    Collection<Integer> list = new ArrayList<>();
    list.add(2);
    list.add(1);
    list.add(0);
    
    for (int i = 0; i < 3; i++) {
      list.remove(i);
      System.out.println("after remove " + i + " -> " + list);
    }
    

    输出:

    after remove 0 -> [2, 1]
    after remove 1 -> [2]
    after remove 2 -> []
    

    此外,通过索引从ArrayList 中删除一个元素并同时不断增加索引也很容易出错:

    list.add(2);
    list.add(1);
    list.add(0);
    
    List<Integer> lst = (List<Integer>) list;
    System.out.println(lst);
    for (int i = 0; i < 3; i++) { // size fixed
      lst.remove(i); // Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 2 out of bounds for length 1
      System.out.println("after remove from list " + i + " -> " + lst);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-20
      • 1970-01-01
      相关资源
      最近更新 更多