
课程咨询: 400-996-5531 / 投诉建议: 400-111-8989
认真做教育 专心促就业
java编程一直以来都是互联网上使用比较广泛的一种编程语言,所以我们今天就一起来了解一下java编程中的抽象类是如何来实现的,希望通过对本文的阅读,大家能够对java编程技术有更深刻的认识,下面就开始今天的主要内容吧。
AbstractMap抽象类实现了一些简单且通用的方法,本身并不难。但在这个抽象类中有两个方法非常值得关注,keySet和values方法源码的实现可以说是教科书式的典范。
抽象类通常作为一种骨架实现,为各自子类实现公共的方法。上一篇我们讲解了Map接口,此篇对AbstractMap抽象类进行剖析研究。
Java中Map类型的数据结构有相当多,AbstractMap作为它们的骨架实现实现了Map接口部分方法,也就是说为它的子类各种Map提供了公共的方法,没有实现的方法各种Map可能有所不同。
抽象类不能通过new关键字直接创建抽象类的实例,但它可以有构造方法。AbstractMap提供了一个protected修饰的无参构造方法,意味着只有它的子类才能访问(当然它本身就是一个抽象类,其他类也不能直接对其实例化),也就是说只有它的子类才能调用这个无参的构造方法。
在Map接口中其内部定义了一个Entry接口,这个接口是Map映射的内部实现用于维护一个key-value键值对,key-value存储在这个Map.Entry中。AbstractMap对这个内部接口进行了实现,一共有两个:一个是可变的SimpleEntry和一个是不可变的SimpleImmutableEntry。
public static class SimpleEntry implements Entry, java.io.Serializable
实现了Map.Entry接口,并且实现了Serializable(可被序列化)。
它的方法比较简单都是取值存值的操作,对于key值的定义是一个final修饰意味着是一个不可变的引用。另外其setValue方法稍微特殊,存入value值返回的并不是存入的值,而是返回的以前的旧值。需要重点学习的是它重写的equals和hashCode方法。
public static class SimpleImmutableEntry implements Entry, java.io.Serializable SimpleImmutableEntry
定义为不可变的Entry,其实是事实不可变,因为它不提供setValue方法,在多个线程同时访问时自然不能通过setValue方法进行修改。它相比于SimpleEntry其key和value成员变量都被定义为了final类型。调用setValue方法将会抛出UnsupportedOperationException异常。
它的equals和hashCode方法和SimpleEntry一致。
接下来查看AbstractMap抽象类实现了哪些Map接口中的方法。
public int size()
Map中定义了一个entrySet方法,返回的是Map.Entry的Set集合,直接调用Set集合的size方法即是Map的大小。
public boolean isEmpty()
调用上面的size方法,等于0即为空。
public boolean containsKey(Object key)
这个方法的实现较为简单,通过调用entrySet方法获取Set集合的迭代器遍历Map.Entry,与参数key比较。Map可以存储为null的key值,由于key=null在Map中存储比较特殊(不能计算hashCode值),所以在这里也做了判断参数key是否为空。
public boolean containsValue(Object value)
这个方法实现和containsKey一致。
public V get(Object key)
这个方法实现和上面两个也类似,不同的是上面相等返回boolean,这个方法返回value值。
public V put(K key, V value)
向Map中存入key-value键值对的方法并没有具体实现,会直接抛出一个UnsupportedOperationException异常。
public V remove(Object key)
通过参数key删除Map中指定的key-value键值对。这个方法也很简单,也是通过迭代器遍历Map.Entry的Set集合,找到对应key值,通过调用Iterator#remove方法删除Map.Entry。
public void putAll(Map m)
这个方法也很简单遍历传入的Map,调用put方法存入就可以了。
public void clear()
调用entrySet方法获取Set集合再调用Set#clear()方法清空。
public Set keySet()
返回Map key值的Set集合。AbstractMap中定义了一个成员变量“transient Set keySet”,在JDK7中keySet变量是由volatile修饰的,但在JDK8中并没有使用volatile修饰。在对keySet变量的注释中解释道,访问这些字段的方法本身就没有同步,加上volatile也不能保证线程安全。关于keySet方法的实现就有点意思了。
public Collection values()
对于values方法则完全可以参考keySet,两者有着异曲同工之妙,这里为节省篇幅不再赘述。
public abstract Set> entrySet()
一个抽象方法,交给它的子类去完成,说明这个方法并不是特别“通用”。
public boolean equals(Object o)
Map中规定只有在Map中的每对key-value键值对的key和value都一一对应时他们的equals比较才返回true。在方法中先判断简单的条件,如果引用相等,直接返回true,如果参数o不是Map类型直接返回false,如果两个Map的数量不同也直接返回false。后面才再遍历Entry数组比较Entry中的key和value是否一一对应。方法简单,但这给了我们一个启示,在条件判断中,先判断简单的基本的,再判断复杂的。
public int hashCode()
重写了Object类的equals方法,重写hashCode也是必须的。AbstractMap对hashCode的实现是将所有Map.Entry(这里就是SimpleEntry或SimpleImmutableEntry)的hashCode值向加,最后得出的总和作为Map的hashCode值。
public String toString()
这个方法没什么好说的,就是取出所有键值对使用StringBuilder对其进行拼接。
作者:OKevin
来源:公众号:coder buff
【免责声明】:本内容转载于网络,转载目的在于传递信息。文章内容为作者个人意见,本平台对文中陈述、观点保持中立,不对所包含内容的准确性、可靠性与完整性提供形式地保证。请读者仅作参考。