问题一:
List(接口) 和 Set(接口) 都继承自 Collection(接口),Set 接口中的方法 和 Collection 中的抽象方法一模一样,全部抄了一遍。List 中的方法也几乎把 Collection 中的方法抄了一遍,然后加了几个特有的抽象方法。本身已经实现了继承关系,为何还要把抽象方法抄一遍呢?
类图

结论:
其实如果详细看过类注释的话,应该能够了解作者为什么这么设计。此种设计是从语义
上来考虑的,而并非纯技术实现层面
。
来看一下 Collection 类注释,截取部分:
集合层次结构中的根接口。集合代表一组对象,称为其元素。一些集合允许重复的元素,而另一些则不允许。
一些是有序的,而其他则是无序的。 JDK不提供此接口的任何直接实现:它提供更特定的子接口(如Set和List)的实现。
一些集合实现对它们可能包含的元素有限制。例如,某些实现禁止使用null元素,而某些实现对其元素类型有限制。
从这里可以看到,Collection 抽象了作为集合的行为准则,是非常粗线条的概念,不同的实现类有不同的实现。例如:还不是允许重复,是不是有序,是不是允许null等等。
再来看一下 Set 类注释,截取部分:
一个不包含重复元素的集合。更正式地说,集合不包含元素对e1和e2,使得e1.equals(e2)最多包含一个空元素。
除了从Collection接口继承的行为准则外,Set接口还对所有构造函数的协定以及add,equals和hashCode方法
的协定规定了其他规定。为了方便起见,此处还包含其他继承方法的声明。 (这些声明附带的规范是针对Set接口量身定制的,
但不包含任何其他规定。)
毫不奇怪,对构造函数的附加规定是,所有构造函数都必须创建一个不包含重复元素的集合(如上定义)。
从注释里,可以了解到 Set 是一个不包含重复数据的集合,是一个 更具体 的集合的抽象。 Set 有 Collection 的所有抽象方法,不多不少。就像注释里所说的,同样是 add
方法,Set、Collection 所编写的方法注释是不一样的,也就说规定了此接口 特有的 规范准则。至于剩下的方法,就像注释里所说的,为了方便起见,此处包含其他继承方法的声明
。何为方便起见,就是一眼就知道此接口有多少抽象的行为规范。
列一下Collection 和 Set、List 针对add
方法的注释,截取部分:
Set:
/**
将指定的元素添加到此集合(如果尚不存在)(可选操作)。 更正式地说,如果集合中不包含任何元素e2,
则将指定的元素e添加到该集合中,使得(e == null?e2 == null:e.equals(e2))。 如果此集合已
包含该元素,则调用将使该集合保持不变并返回false。
*/
boolean add(E e);
List:
/**
将指定的元素追加到此列表的末尾(可选操作)。
支持此操作的列表可能会限制可以添加到此列表的元素。 特别是,某些列表将拒绝添加空元素,
而另一些列表将对可能添加的元素类型施加限制。列表类应在其文档中明确指定对可以添加哪些元素的任何限制。
*/
boolean add(E e)
Collection:
/**
确保此集合包含指定的元素(可选操作)。 如果此集合由于调用而更改,
则返回true。 (如果此集合不允许重复并且已经包含指定的元素,则返回false。)
支持此操作的集合可能会对可以添加到此集合的元素施加限制。 特别是,某些集合将拒绝添加null元素,
而其他集合将对可能添加的元素类型施加限制。 集合类应在其文档中明确指定对可以添加哪些元素的任何限制。
如果某个集合由于已经包含该元素以外的其他原因拒绝添加该元素,则它必须引发异常(而不是返回false)。
这保留了不变,即在此调用返回之后,集合始终包含指定的元素。
*/
boolean add(E e);
Collection 的 add
方法几乎把所有的情况都定义了, Set 和 List 的add
方法是 更特定的、特有的 准则。这些都是语义
上的规范,有助于 阅读、理解和分类。当然,如果从纯技术角度考虑,这些重复的方法定义,其实都是可以不写的。了解了作者的想法以后,会觉得确实这么做会更好。
集合类层级结构中,越往上层,抽象粒度越高,越往下层,抽象粒度越细,抽象也越具体,每层的接口的都对该层的抽象方法做了相应的约束,是约束也是规范。即使不同的层级中有相同的抽象方法,可能所代表的的约束已完全不同。
问题二:
ArrayList 继承自 AbstractList,AbstractList 实现了 List 接口。为何ArrayList 类定义的时候 还要实现 List接口?是不是有点多余?**
类图

结论:
此种设计是从语义
上来考虑的,而并非纯技术实现层面
。会让阅读的人第一眼就知道 这是一个 List 的实现。
比如,第一眼看到 Vector
这个集合时,就知道 它是一个 List
,即使不用太细节的了解实现就能用起来,因为他一定有一个 add
和 get
方法,有利于 理解 、 使用 和 分类
列一下 Vector
的定义:
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
网友评论