背景
序列化
在编码过程中,我们也会遇到将使用的对象信息通过网络传输到另一端,又或者将对象信息保存下来,存储成文件形式保存在电脑硬盘上,以供下次提取使用,我们把 抽取对象信息并转化为二进制形式流的过程称之为序列化过程。
持久化
将信息持久化指的是将信息存储在不易失媒介上,内存上的信息在电脑断电后都会消失,而诸如硬盘、磁带等设备上的信息不会丢失,所以称这些数据是持久的,所以和数据库相关的层也会被称为持久化层,因为他们的工作就是将数据持久化存储。
transient 意义
transient,英文名字就是瞬态的意思,意思是这个信息只是暂时在这个特定情况有意义,和计算机中持久的相对,需要持久化的信息代表这个信息在长远有一定意义。
java中对transient关键字的作用有如下描述:
Variables may be marked
transient
to indicate that they are not part of the persistent state of an object. —— 摘自java手册当类成员字段被表明为transient时,则表明这个字段信息不具有将其持久保存或转化的意义。
transient只能用在类字段上,如果加上,表示该字段不需要转化,否则将其转化。
Attention:不是所有的对象都能转化,只有实现了serialiable接口的类成员对象才能转化
class Point implements Serializable{
int x, y; //这两个会被序列化
transient float rho, theta; //这两个字段信息不会被转化
}
serializable接口
transient关键字与serialiable接口 意义区分
java使用serializable接口来标记一个类是否可以序列化。
transient关键字则说明了某个字段是否需要序列化。
必须实现了serializable接口的类中再去使用transient关键字,否则没意义啊!毕竟你要先决定这个类可不可以序列化,再去决定需要序列化哪些信息。
serializable的实现
去看java源代码,发现serializable接口中并没有任何方法,是一个空的接口。
空的接口没什么意义啊,为什么要这么做呢?经查询,原来这个接口只是起到一个标记的作用,不具有其他意义,他告诉jvm这个类是可以序列化的。
那么具体的序列化是怎么实现的呢?
通过ObjectOutputStream和ObjectInputStream两个类实现。
objectOutputStream.writeObject(object /*参数为需要序列化的类*/); // 序列化
objectInputStream.readObject(object); // 解序列化
例子
class NameStore implements Serializable{
private String firstName;
private transient String middleName; //这个字段不会被序列化
private String lastName;
public NameStore (String fName, String mName, String lName){
this.firstName = fName;
this.middleName = mName;
this.lastName = lName;
}
public String toString(){
StringBuffer sb = new StringBuffer(40);
sb.append("First Name : ");
sb.append(this.firstName);
sb.append("Middle Name : ");
sb.append(this.middleName);
sb.append("Last Name : ");
sb.append(this.lastName);
return sb.toString();
}
}
public class TransientExample{
public static void main(String args[]) throws Exception {
NameStore nameStore = new NameStore("Steve", "Middle","Jobs");
ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("nameStore"));
// writing to object
o.writeObject(nameStore);
o.close();
ArrayList
// reading from object
ObjectInputStream in = new ObjectInputStream(new FileInputStream("nameStore"));
NameStore nameStore1 = (NameStore)in.readObject();
System.out.println(nameStore1);
}
}
输出:
First Name : Steve Middle Name : null Last Name : Jobs
可见,MiddleName没有被序列化。
FAQ
-
什么样的数据可以序列化,什么样的不可以呢?
什么样的对象从根本来说都可以序列化,但是有的对象序列化是没有意义的,比如socket和文件等,所以这些类没有实现Serializable接口,也就不能序列化。
-
很多类种有SerialVersionUID,它是用来干嘛的?
这个UID为每个类生成了一个唯一标识符,如此jvm可以利用这个标识符来比较序列化和解序列化过程中两个类是不是相同,以确保解序列化时的类加载正确。如果你没有自己主动生成,jvm会自动帮你制定一个。
参考
1.java规范说明
2.Java: What can and what can’t be serialized?