什么是序列化
序列化就是將對(duì)象轉(zhuǎn)化為字節(jié)流
反序列化就是將字節(jié)流轉(zhuǎn)化為對(duì)象
序列化的作用
1.將對(duì)象保存到磁盤上
2.在網(wǎng)絡(luò)傳輸對(duì)象
如何序列化
繼承序列化接口Serializable
transient關(guān)鍵字,指定元素不會(huì)進(jìn)行jvm默認(rèn)的序列化
例如:private transient int age;
則在反序列化中拿不到age的值,就會(huì)取得int的默認(rèn)值0
不過我們可以自己實(shí)現(xiàn)序列化启盛,具體請(qǐng)看代碼
serialVersionUID的作用
防止反序列化失敯剖 (當(dāng)修改了這個(gè)類的時(shí)候肘交,可能反序列化會(huì)失斠膊)
序列化時(shí)博脑,會(huì)將這個(gè)值寫入某個(gè)地方,反序列化時(shí)會(huì)對(duì)比這個(gè)值炭玫,如果不一致則會(huì)失敗,因此一般都將該值指定為1L
一個(gè)類實(shí)現(xiàn)了序列化接口貌虾,它的子類都可以進(jìn)行序列化
序列化流
ObjectOutputStram writeObject
反序列化流
ObjectInputStream readObject
下面我來上一段代碼
public class Worker implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private String sex;
private int age;
//關(guān)注點(diǎn)1
private transient int i; // 指定元素不會(huì)進(jìn)行jvm默認(rèn)的序列化 ,但是可以自己實(shí)現(xiàn)序列化础嫡,見代碼最下面
public int getI() {
return i;
}
public void setI(int i) {
this.i = i;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//關(guān)注點(diǎn)2
// 自己實(shí)現(xiàn)序列化
private void writeObject(ObjectOutputStream oos) throws IOException {
oos.defaultWriteObject();
oos.writeInt(i);
System.out.println("session serialized");
}
//關(guān)注點(diǎn)3
// 自己實(shí)現(xiàn)反序列化
private void readObject(ObjectInputStream ois) throws IOException,
ClassNotFoundException {
ois.defaultReadObject();
i = ois.readInt();
System.out.println("session deserialized");
}
}
public class RWObject {
public static void main(String[] args) {
// TODO Auto-generated method stub
String path = "/Users/sufan/Desktop/worker.txt";
// 創(chuàng)建一個(gè)對(duì)象
Worker worker = new Worker();
worker.setName("張三");
worker.setSex("男");
worker.setAge(20);
worker.setI(10);
// 創(chuàng)建一個(gè)文件
File file = new File(path);
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//關(guān)注點(diǎn)4
// 將對(duì)象保存到文件
try {
FileOutputStream fos = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(worker);
oos.close();
fos.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//關(guān)注點(diǎn)5
// 從文件中讀取對(duì)象
try {
FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fis);
Worker worker2 = (Worker) ois.readObject();
System.out.println(worker2.getName());
System.out.println(worker2.getSex());
System.out.println(worker2.getAge());
System.out.println(worker2.getI());
ois.close();
fis.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
輸出結(jié)果
張三
男
20
10
結(jié)果分析
關(guān)注點(diǎn)1,定義了一個(gè)transient類型的變量
關(guān)注點(diǎn)2酝惧,重寫了readObject方法榴鼎,這個(gè)方法的作用就是序列化
關(guān)注點(diǎn)3,重寫了writeObject方法晚唇,這個(gè)方法的作用就是反序列化
關(guān)注點(diǎn)4巫财,通過writeObject,將worker對(duì)象寫入了文件
關(guān)注點(diǎn)5哩陕,通過readObject平项,從文件中讀取了worker對(duì)象
如果我們不重寫readObject和writeObject方法赫舒,則最終i的輸出應(yīng)該是0.