【Java基础】AbstractList、AbstractSet、AbstractCollection的介绍

1,313 阅读6分钟

上一期我们讲到List、Set、Collection、Iterable四个接口的关系和功能,同时也介绍了接口是用来规范代码的,这一期我们来讲一下AbstractList、AbstractSet和AbstractCollection,是因为细心的人会发现JDK提供的List、Set的常用实现类,比如ArrayList、Vector、LinkedList、TreeSet、HashSet、LinkedHashSet,这些实现类除了实现类List或Set接口,他们还都继承自AbstractList或AbstractSet类,而AbstractList和AbstractSet类又继承自AbstractCollection类,所以基于这个情况,我今天再从AbstractList、AbstractSet和AbstractCollection来介绍一下List、Set、Collection。

0. 知识储备

0.1 抽象类(AbstractClass)是什么

我觉得首先你得知道Abstract这个单词是什么意思

这里面有一个解释我觉得很重要,纯理论的,结合Java我们可以理解为Abstract类主要用于描述某种概念,他并不会有实体。这样说有点抽象,我来举个例子,比如说食物就是一种概念,很多东西都可以称为食物,但食物这个词本身只是一种概念,并没有实物,而草莓、巧克力、牛奶就是食物的具体表现形式。那么食物里有草莓、巧克力、牛奶,然后草莓、巧克力、牛奶都是食物,即食物是草莓、巧克力、牛奶的共性,也就能间接的描述Abstract类的作用就是描述某种概念,即某一类事物的共性。

0.2 接口与静态类

由上一期所述,接口的作用其实是在规范代码,告诉大家实现类应该有哪些参数、方法。其实这就已经是在描述一类事物的共性了,那为什么还需要静态类呢?这个需要分两段来讲

0.2.1 Java8之前

在Java8之前,首先是接口里面的变量都是静态常量,而抽象类和普通类一样,其次是接口只能写函数,不能写具体的函数内容,而抽象类能写函数,还能写函数的具体实现,所以通常我们认为,接口用于抽象功能,而抽象类用于抽象类别。其实我觉得挺混淆的,我都写在抽象类里面我觉的就挺好,但是JVM我不是怎么了解,接口和抽象类的运行我觉得应该还是有某些区别的,这一点在以后我再深究。

0.2.2 Java8之后

Java8之后,引入了接口可以编写默认方法,什么意思呢,就是从Java8开始,接口和抽象类都可以定义函数的具体内容了,那剩下的区别就只有成员变量了。其实我总有预感这个抽象类会被慢慢取缔,都是用来规范、定义的概念性的东西,接口可多实现,类却不能多继承,在当下这个时代,很多概念其实都越来越模糊了,比如牛奶,我说他是液体也行,是食物也行,但不是所有液体都是食物,也不是所有食物都是液体,但我只能继承一个类,你怎么设计这个抽象类呢?液体食物类?现在接口引入了默认方法其实就已经在动摇抽象类的地位了,所以我认为其实以后接口肯定是会逐渐引入普通成员变量这一点的,那时抽象类就会逐渐退出大家的视线。

话虽这么说,但依据林迪效应来看,抽象类至少还能活个五六年,再基于Java开始收费以及国内企业在Java新版本的拥抱程度来看,抽象类和接口依然是大家需要学习的知识点。

1. UML图

文章开头说了很多啊,但一图胜千言的道理也给大家普及一下,一张UML图告诉你我为什么写这一期内容(蓝色实线是类的继承,绿色实线是接口的继承,绿色虚线是接口实现)

2. 通过源码注释看看他们规范了什么共性

2.1 AbstractCollection

This class provides a skeletal implementation of the Collection interface, to minimize the effort required to implement this interface. 此类提供了Collection接口的基本实现,以最大程度地减少实现此接口所需的工作

The documentation for each non-abstract method in this class describes its implementation in detail. 此类中每个抽象方法都有详细的注释。

(注释未完全展示)其实即使通过全部注释也看不出AbstractCollection能规范啥,同时还规范了实现可修改或不可修改的集合需要怎么做,他更多的是以Collection接口的扩展存在的。

2.2 AbstractList

This class provides a skeletal implementation of the List interface to minimize the effort required to implement this interface backed by a "random access" data store (such as an array). For sequential access data (such as a linked list), AbstractSequentialList should be used in preference to this class. 此类提供List接口的具体实现,减少实现“随机访问”存储模式的集合所需的工作。对于要实现顺序访问数据的集合,应优先使用AbstractSequentialList。

(注释未完全展示)可以看出AbstractList在List接口规范之外,又引入了一种随机访问的规范,其次注释仍然是规范实现不可修改、可修改的集合需要实现哪些方法。

2.3 AbstractSequentialList

This class provides a skeletal implementation of the List interface to minimize the effort required to implement this interface backed by a "sequential access" data store (such as a linked list). For random access data (such as an array), AbstractList should be used in preference to this class. 此类提供List接口的具体实现,减少实现顺序访问存储模式的集合所需的工作。对于要实现随机访问数据的集合,应优先使用AbstractList

(注释未完全展示)同样的,相对于AbstractList来说,AbstractSequentialList引入了一种顺序访问的规范,其余的注释同样在规范可修改、不可修改登记和需要实现哪些方法。

2.4 AbstractSet

This class provides a skeletal implementation of the Set interface to minimize the effort required to implement this interface. 此类接口提供Set接口的基本实现,以最大程度的解散实现Set接口所需的工作

The process of implementing a set by extending this class is identical to that of implementing a Collection by extending AbstractCollection, except that all of the methods and constructors in subclasses of this class must obey the additional constraints imposed by the Set interface (for instance, the add method must not permit addition of multiple instances of an object to a set). 通过扩展此类来实现集合的过程和通过扩展AbstractCollection来实现Collection的过程相同,不同之处在于,此类的子类中,所有的方法和构造函数必须服从Set接口提供的规范(例如:add方法不得允许将一个对象的多个实例添加到一个集合中)

(注释未完全展示)显而易见啊,AbstractSet同样只是作为Set接口的一个扩展,并没有额外的规范。

3. 思考

从上面四个抽象类的注释来看,官方似乎持有抽象类是接口的扩展这种想法,这也是我为什么觉得接口会越来越强大的原因,接口只要更完善了,那我还需要你给我扩展什么吗?这是我最直观的想法,其次,关于AbstractList、AbstractSequentialList两个类的注释,顺序访问和有序访问概念的实现,其实在注释了我觉得已经有写了,这也将影响到他们的子类ArrayList和LinkedList的实现有什么区别,但我没有放上来,因为我还想有一期专门讲ArrayList、LinkedList、Vector、TreeSet、HashSet、LinkedSet的文章,所以下期在见。