问:什么是Java序列化?
答:Java提供了两种对象持久化的方式,分别为序列化和外部序列化。
- 序列化(Serialization)
在分布式环境下,当进行远程通信时,无论是何种类型的数据,都会以二进制序列的形式在网络上传送。序列化是一种将对象以一连串的字节描述的过程,用于解决在对对象流进行读写操作时所引发的问题。序列化可以将对象的状态写在流里进行网络传输,或者保存到文件、数据库等系统里,并在需要时把该流读取出来重新构造一个相同的对象。
如何实现序列化呢?其实,所有要实现序列化的类都必须实现Serializable接口,Serializable接口位于java.lang包中,它里面没有包含任何方法。使用一个输出流(例如FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,紧接着,使用该对象的writeObject(Objectobj)方法就可以将obj对象写出(即保存其状态),要恢复时可以使用其对应的输入流。
序列化有以下两个特点:
1)如果一个类能被序列化,那么它的子类也能够被序列化。
2)由于static(静态)代表类的成员,transient(Java语言关键字,如果用transient声明一个实例变量,当对象存储时,它的值不需要维持。)代表对象的临时数据,因此被声明为这两种类型的数据成员是不能够被序列化的。
Java提供了多个对象序列化的接口,包括ObjectOutput、ObjectInput,ObjectOutputStream和ObjectInputStream。
由于序列化的使用会影响系统的性能,因此如果不是必须要使用序列化,应尽可能不要使用序列化。那么在什么情况下需要使用该序列化呢?
1)需要通过网络来发送对象,或对象的状态需要被持久化到数据库或文件中。
2)序列化能实现深复制,即可以复制引用的对象。
与序列化相对的是反序列化,它将流转换为对象。在序列化与反序列化的过程中,serialVersionUID起着非常重要的作用,每个类都有一个特定的serialVersionUID,在反序列化的过程中,通过serialVersionUID来判定类的兼容性。如果待序列化的对象与目标对象的serialVersionUID不同,那么在反序列化时就会抛出InvalidClassException异常。作为一个好的编程习惯,最好在被序列化的类中显式地声明serialVersionUID(该字段必须定义为static final)。自定义serialVersionUID主要有如下3个优点:
- 提高程序的运行效率。如果在类中未显式声明serialVersionUID,那么在序列化时会通过计算得到一个serialVersionUID值。通过显式声明serialVersionUID的方式省去了计算的过程,因此提高了程序的运行效率。
- 提高程序不同平台上的兼容性。由于各个平台的编译器在计算serialVersionUID时完全有可能会采用不同的计算方式,这就会导致在一个平台上序列化的对象在另外一个平台上将无法实现反序列化的操作。通过显式声明serialVersionUID的方法完全可以避免该问题的发生。
- 增强程序各个版本的可兼容性。在默认情况下,每个类都有唯一的serialVersionUID,因此,当后期对类进行修改时(例如加入新的属性),类的serialVersionUID值将会发生变化,这将会导致类在修改前对象序列化的文件在修改后将无法进行反序列化操作。同样,通过显式声明serialVersionUID也会解决这个问题。
- 外部序列化
Java语言还提供了另外一种方式来实现对象持久化,即外部序列化。其接口如下:
外部序列化与序列化主要的区别在于序列化是内置的API,只需要实现Serializable接口,开发人员不需要编写任何代码就可以实现对象的序列化,而使用外部序列化时,Externalizable接口中的读写方法必须由开发人员来实现。因此与实现Serializable接口的方法相比,使用Externalizable编写程序的难度更大,但是由于把控制权交给了开发人员,在编程时有更多的灵活性,对需要持久化的那些属性可以进行控制,可能会提高性能。
引申:在用接口Serializable实现序列化时,这个类中的所有属性都会被序列化,那么怎样才能实现只序列化部分属性呢?
一种方法为实现Externalizable接口,开发人员可以根据实际需求来实现readExternal与writeExternal方法来控制序列化与反序列化所使用的属性,这种方法的缺点为增加了编程的难度。另一种方法为使用关键字transient来控制序列化的属性。被transient修饰的属性是临时的,不会被序列化。因此,可以通过把不需要被序列化的属性用transient来修饰。
本文暂时没有评论,来添加一个吧(●'◡'●)