我们通过阅读Java集合接口的源代码:Collection, Set, List, Queue, Deque,发现它们之间会有接口继承的关系,但是我们会发现一个奇怪的问题,下面细细说来。
我们可以看到Deque接口的源码
public interface Deque<E> extends Queue<E> {
// 这里是Deque特有的方法,对问题的讨论不产生影响,省略
// *** Queue methods ***
boolean add(E e);
boolean offer(E e);
E remove();
E poll();
E element();
E peek();
// *** Collection methods ***
boolean remove(Object o);
boolean contains(Object o);
public int size();
Iterator<E> iterator();
Iterator<E> descendingIterator();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Deque是继承自Queue的,而Queue是继承自Collection的。
public interface Queue<E> extends Collection<E> {
// 插入
boolean add(E e); //
boolean offer(E e); // 只用在有界队列中
// 移除并返回值
E remove(); // 队空,抛出异常
E poll(); // 队空,返回false
// 只取值
E element();
E peek();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
我们再看Collection的源码:
public interface Collection<E> extends Iterable<E> {
int size();
boolean isEmpty();
boolean contains(Object o);
Iterator<E> iterator();
boolean add(E e);
boolean remove(Object o);
// 其它的方法就省略了,对问题的讨论没影响
}
1
2
3
4
5
6
7
8
9
我们发现在Deque接口的源码中,仍然列出了继承自Queue的方法,还有继承自Collection的方法(官方源码作者自己也作了注释:// *** Collection methods ***,// *** Queue methods ***)。我们学过接口的继承知道:子接口会继承父接口的接口方法,这样我们在子接口中没必要再声明父接口中已经存在的抽象方法了。
但是JDK中Java集合框架的接口继承源码中并没有这样子,而是在每个接口中都会重新列出一部分父接口的抽象方法。为啥Java集合框架的开发者不好好利用继承的代码重用特性呢?下面是网络上给出的答案,我觉得挺好。
java编程思想 第四版 第231页有这么一段话:
Set具有与Collection完全一样的接口方法,因此没有任何额外的功能,不像前面有两个 >不同的List。实际上Set就是Collection,只是行为不同。(这是继承与多态思想的典型 >应用:表现不同的行为。)
仅仅为了代码的可读性。从语法上说的确不是必须的。
即使同一个方法,上面的注释是不一样的。
API就是要让人看懂,在A集合里定义a方法,解释跟A有关的信息
然后B集合继承A集合,同样有a方法,但是要对a方法重新说明一下,怎么办?是不是要重新写一遍?就是这个情况了
我们知道,当我们去Oracle Java API网站查阅Java API时,网站都会给出API的用途/释意。而子接口的方法用途与父接口的用途很可能不一致,那么我们就需要重新地给出一个特别的注释说明。
正如上面所说的:Collection接口与Set接口的抽象方法完全相同,那么当我们声明Set的时候,是否可以对此接口的内容置空,什么抽象方法也不声明呢?本质上是可以这样做的!因为两者的方法确实是相同的,通过继承我们能够全部继承过来。
public interface Set<E> extends Collection<E> {
// 这里为空,什么抽象方法也不声明
}
1
2
3
如果这样做,会发生什么情况?开发人员开发完这些类之后,使用javadoc生成API参考文档,此时问题就糟了——Set类没有方法说明,全是继承自Collection的方法链接,要查看非常麻烦,并且我们通过Collection的方法并不能够知道Set对应方法的具体意义。Set与Collection在接口的抽象方法上虽然是一模一样的,但是它们在现实生活中的意义却有着较大的差距,我们需要对泛化的Collection作Set自己专有的注释!
Method Summary
...
Methods inherited from interface java.util.Collection
parallelStream, removeIf, stream,.....