为什么LinkedHashMap类实现Map接口?

7

HashMap类实现了Map接口:

public class HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable

LinkedHashMap是继承自HashMap的一个类,因此它默认应该实现Map接口。那么为什么还要明确地实现Map接口呢?

public class LinkedHashMap<K,V>
extends HashMap<K,V>
implements Map<K,V>
4个回答

5
你说得对:在链接哈希映射的声明中删除 Map 不会改变任何事情。虽然 LinkedHashMap 简单地实现了 Map,因为它继承自 HashMap,但是链接哈希映射从普通哈希映射派生的事实是一个实现细节,而不是硬性要求。
另一方面,实现 Map 接口是一个基本要求。如果设计者决定从头开始实现 LinkedHashMap,或者依赖于其他基类,例如链表,则此要求将不会消失。
这就是为什么 LinkedHashMap 的设计者明确提到了 Map:如果在以后某个时候基类由于重新设计而更改,则接口将保持不变。

4

这么做可能是为了让文档更加清晰,但它对代码本身没有任何影响。这也可能是因为LinkedHashMap extends HashMap只是一种实现细节,真正重要的是知道LinkedHashMap是一个Map


3

实际上两者没有区别。在我的观点中,JDK类中一直存在这种模式(List及其子类也是如此)。设计者可能还没有删除这个多余的实现,以防万一有人依赖反射来获取有关子类型的信息而导致破坏。例如,想象一下您定义了以下内容:

class MyCustomMap<K, V> extends LinkedHashMap<K, V> implements Map<K, V> {

}

接下来的代码片段在有和没有 implements 的情况下输出不同的结果:

Class<?>[] interfaces = MyCustomMap.class.getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
    System.out.println(interfaces[i]);
}

输出:

接口 java.util.Map

将定义更改为:

class MyCustomMap<K, V> extends LinkedHashMap<K, V> {

}

那么就不会打印任何界面。


有趣的想法,但你尝试过不使用 implements Map 吗?你可以很容易地模拟这个。 - Dici
@Dici 如果没有使用implements,输出中不会显示任何接口。 - M A
1
嗯,如果有人以那种方式使用反射,那么这本身就是一个错误。通常我们应该像这样做:for (Class<?> c = C.class; c != Object.class; c = c.getSuperclass()) {...}。如果Map是为了这个原因而实现的,那么它将是为了依赖于不当使用getInterfaces的人而存在的。 - Radiodef
2
@Radiodef 我同意你的观点。理想情况下,Dici的解释更有说服力。我的观点是要展示两个版本之间的代码差异。 - M A

1

Dici的说法在大部分情况下是正确的。

很久以前,一些较差的Java编译器可能会有点混乱,偶尔我也会添加(到我的代码中)应该源自父层次结构的接口。也许这也有助于将接口放置在多个位置(Java库中),但这只是纯粹的猜测。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接