集合中某些类或者接口继承或者实现了标记接口(Marker Interface),这里大概说下几个常用的标记接口的用处与底层实现。
标记接口
在集合类中涉及到下列几个标记接口(Marker Interface)
Cloneable
标记该类可以浅拷贝
- 浅拷贝只拷贝对象参数的基本类型部分,如果要拷贝引用类型,达到深拷贝的目的,需要覆写 Object.clone() 方法。
Serializable
标记该类产生的对象可序列化
- 可以通过
ObjectInputStream
与ObjectOutputStream
来获取或者写入Java
独有的序列化方式序列化过的对象; - 其中
serialVersionUID
为兼容模型而设计(这里的设计不存在安全性考虑,因为明文传输),如果没有设定,JVM
会根据当前序列化的类的结构计算校验和,得到一个固定的Long
值,但当类结构改变时UID
也会随之改变,所以为了防止序列化失败,除非不想兼容之前模型,这里建议还是设定一个serialVersionUID
; - 获取类定义时,还通过
ConcurrentHashMap<WeakClassKey, SoftReference>
来保存 序列化对象的Class
(继承自WeakReference
)和 即将序列化的对象定义实体(在SoftReference
中保存ObjectStreamClass
或EntryFuture
等),用来辅助暂存序列化类的定义; - 像
ArrayList
、HashMap
等存在部分数组索引的值为空的情况,为了序列化/反序列化过程中不产生空元素,Serialzable
提供了writeObject
,readObject
等私有方法来定制序列化方式; - 对象参数存在
transient
但想序列化的情况,同样可以通过4
的方法实现; writeObject
,readObject
等方法参数序列化、反序列化时存在顺序性(类似Protobuf
的IDL
有索引),这点需要注意。
RandomAccess
标记为支持快速随机访问的类
- 标记该类数据模型底层使用数组,查询时间复杂度为
O(n)
,推荐遍历优先使用索引而不是迭代器。
Externalizable
标记为自定义序列化方式
- 有两个待实现接口
writeExternal
和readExternal
; Externalizable
接口优先级高于Serializable
,如果实现该接口,Serializable
的隐式定义方法,如:writeObject
,readObject
等都不会生效。