有关Java的HashMap的实现的问题

在Java中,对于HashMap的定义是这样的:

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

 我想知道的是,为什么HashMap的父类AbstractMap已经implements了Map<K,V>接口,而在HashMap的定义中又再一次的声明implements Map<K,V>接口呢,这么做有什么意义呢?

 

我记得我学长给我的答案是为了更好的面向接口编程,但有些模糊,请大家指导一下;

5个回答

从编译和运行的角度来说,没有意义。
但是从读者的角度来说,有意义。

你可以考虑一下如下场景:
1,你定义了一个接口,里面有10个抽象方法(接口里面的都是抽象方法)
2,你有9个抽象类,抽象类1继承接口,实现了1个方法(可以只实现接口的部分方法)
3,抽象类2继承抽象类1,同时又多实现了一个方法
4,依次类推,每个抽象类依次继承上面的抽象类,每个都多实现一个方法。
5,最后你的实现类实现抽象类9,把最后一个未实现的方法实现了。
那么问题来了
这时候你读源代码或者文档的时候,你根本不知道你这个类实现了什么接口,如果想知道的话,就要依次把抽象类9,8。。。一直找到抽象类1的时候,你才知道你的这个实现类实际上是实现了你第一步定义的接口,这样是不是对读者很不友好?

如果每一层都明确声明实现了第一步的接口,那么你看实现类或者任一层次的抽象类的时候,你都不需要再找别的继承关系的类了,因为你可以直接跳到接口去看定义就可以了。

这就是对读者友好的体现,推荐你以后的开发中注意这一点,代码主要是给人看的,对于机器来说,他只需要2进制字节就可以了。

#你学长是忽悠你的,愿意钻研是好习惯,希望保持下去!

u012724379
-骑着乌龟去看海- 快实习了,不过懂的还是很少,看能不能找到个公司去实习去呢;
大约 5 年之前 回复
weixin_42622339
weixin_42622339 没毕业能这么爱钻研真好,那就给分结贴吧。
大约 5 年之前 回复
u012724379
-骑着乌龟去看海- 谢谢指导,我还没毕业呢,嘿嘿;
大约 5 年之前 回复
u012724379
-骑着乌龟去看海- 嗯,或许我对面向接口编程的理解就是等同于面向Java Interface编程,嗯,谢谢,我明白了;
大约 5 年之前 回复
weixin_42622339
weixin_42622339 面向接口编程和接口实现在哪一个继承层次没有关系,甚至说,和你是否用了接口没有都没有关系。 比如Python,Javascript这些语言,没有接口的定义语法,难道就不能面向接口编程了吗?不是的。 你可以理解为面向约定编程。 最俗的例子就是,每个灯都不用你开发新的开关,你做一个新灯的开关,只要满足开关厂商的定义就可以了,这样做出的灯的开关肯定就好使,这个灯开关接口的定义实际上就是一些描述,是你和厂商的约定,厂商不会给你提供一个具体的接口模板让你在上面焊东西的对吧。 所以,面向接口不要理解得那么狭义,接口可以是Inteface,可以是webAPi,也可以是一个普通方法,甚至就是一个约定。很多人理解得静态语言(比如Java里面)把面向接口编程给等同于了面向Java Interface编程,这是不对的。 楼下说的对JavaDoc有影响的分析是对的,你可以生成一下看看。 至于说对方法的重载还是覆盖或者继承层次有影响那就是胡说了。
大约 5 年之前 回复
u012724379
-骑着乌龟去看海- 可是为什么也有说是为了面向接口编程呢,看楼下,就有这一说法;
大约 5 年之前 回复
u012724379
-骑着乌龟去看海- 嘿嘿,我英文不太好,但竟然大致看懂了;that it was a mistake,或许真是个错误呢,应该是真为了可读性呢;
大约 5 年之前 回复
weixin_42622339
weixin_42622339 可以看看这位老大的介绍,你用的不管是Map还是ArrayList啥的都是这位大哥写的,他的观点你总能接受了吧。 http://en.wikipedia.org/wiki/Joshua_Bloch
大约 5 年之前 回复
weixin_42622339
weixin_42622339 英文还可以的话,看看下面这2篇文章: http://stackoverflow.com/questions/11028542/why-does-atomicinteger-implements-serializablehttp://stackoverflow.com/questions/2165204/why-does-linkedhashsete-extend-hashsete-and-implement-sete?lq=1 其中一篇文章的答案是Java的Collections Framework的作者的观点,这个够官方了吧。 基本上,就是为了文档的可读性。
大约 5 年之前 回复
weixin_42622339
weixin_42622339 没有的,可以自己编译之后通过字节码观察下
大约 5 年之前 回复
u012724379
-骑着乌龟去看海- 从编译和运行来说,难道一点意义都没有嘛
大约 5 年之前 回复

AbstractMap 和 Hashmap 里面都有对map的实现,
如果HashMap不implements Map, 那就是HashMap对AbstractMap 方法的[b]覆盖[/b].
如果implements Map, 那就是对Map接口的[b]实现[/b].

这个从语法方面讲,还是有些区别的.

u012724379
-骑着乌龟去看海- 或许是为了可读性呢;
大约 5 年之前 回复
flyfoxs
flyfoxs 我也的确是没感觉到有什么区别,但是编译期是能发现的. 你看看方法旁边的提示.他会提示这个方法是实现接口的,还是覆盖父类的.
大约 5 年之前 回复
flyfoxs
flyfoxs 这就对了,好的设计,就是让你用得舒坦,感觉不到他的存在.要是用得时候都有小心翼翼的就难受了.
大约 5 年之前 回复
u012724379
-骑着乌龟去看海- 但是用的时候感觉有和没有 没有区别呢;
大约 5 年之前 回复

对“更好的面向接口编程”表示同意。

通过源码可知:
1:AbstractMap对“实现Map接口所需做的工作”进行了最小化,
即当需实现“unmodifiable不可修改”/“modifiable可修改”的Map时只需少量工作;
2:HashMap实现了Map接口的所有方法,除了clone()外无其他方法使用super,实现了AbstractMap中的entrySet方法;
所以HashMap代码逻辑与AbstractMap的关系很小,类之间只有extend关系。


概念:父类引用指向子类对象
代码:
[code="java"]
HashMap map = new HashMap();
AbstractMap aMap = map;
Map mMap = map;
[/code]
HashMap实例可以被AbstractMap或Map引用,实际使用更灵活。

1、与面向接口编程没什么关系,因为不管是否声明implements Map,对于使用者来说都没有什么影响;

2、这个模式在JDK的很多集合类里面都在使用,我本人更倾向于增强可读性的说法
。看了HashMap的Javadoc马上就知道是实现了Map的接口(当然,通过AbstractMap也是可以知道的)
。对Map接口的Javadoc,能够明确的知道哪些类实现了这个接口:我没有测试过,猜想可能是生成Javadoc的时候对于接口的Implement只识别了一层,这样的情况下如果不明确声明的情况下接口的实现类列表里面就没有HashMap了。

u012724379
-骑着乌龟去看海- 如果仅仅从文档的角度来讲,那的确是倾向于增强可读性呢;
大约 5 年之前 回复
u012724379
-骑着乌龟去看海- 或许很大概率是为了增强可读性呢;
大约 5 年之前 回复

学习下~~~~~~~~~~~~

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!