Java序列化與反序列化
Java 序列化與反序列化
Java序列化把一個(gè)對(duì)象Java Object變?yōu)橐粋€(gè)二進(jìn)制字節(jié)序列byte[]
Java反序列化就是把一個(gè)二進(jìn)制字節(jié)序列byte[] 變?yōu)镴ava對(duì)象Java Object
序列化API
ObjectOutputStream
字節(jié)輸出流對(duì)象,將對(duì)象的輸出流寫到文件中(結(jié)合FileOutputStream使用)
實(shí)例:
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("1.txt"));
或
FileOutputStream fout = new FileOutputStream("1.txt");
ObjectOutputStream out = new ObjectOutputStream(fout);
此外ObjectOutputStream還提供了writeObject()方法來序列化一個(gè)對(duì)象,并將它發(fā)送到輸出流。
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("1.txt"));
out.writeObject(new Test("Sentiment",10)); //對(duì)Test類中的構(gòu)造方法進(jìn)行傳參
ObjectInputStream
字節(jié)輸入流對(duì)象,將文件中的二進(jìn)制字節(jié)序列進(jìn)行反序列化操作(結(jié)合FileInputStream)
實(shí)例:
ObjectInputStream in = new ObjectInputStream(new FileInputStream("1.txt"));
或
FileInputStream fin = new FileInputStream("1.txt");
ObjectInputStream oin = new ObjectInputStream(fin);
此外ObjectInputStream還提供readObject()方法從流中取出下一個(gè)對(duì)象,并將對(duì)象反序列化。它的返回值為Object,因此,需要將它轉(zhuǎn)換成合適的數(shù)據(jù)類型。
ObjectInputStream In = new ObjectInputStream(new FileInputStream("1.txt"));
Test o = (Test)In.readObject();
System.out.println(o); //讀取后輸出實(shí)例理解實(shí)例理解
Test.java(類想要進(jìn)行序列化操作,必須實(shí)現(xiàn)Serializable接口繼承)
package Sentiment.unserialize.demo01;
import java.io.Serializable;
public class Test implements Serializable {
private String name;
private int age;
public Test() {
}
public Test(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Test{" + "name='" + name + '\'' + ", age=" + age + '}';
}
}
Serializable.java
package Sentiment.unserialize.demo01;
import java.io.*;
public class Serializable {
public static void main(String[] args) throws IOException {
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("1.txt"));
out.writeObject(new Test("Sentiment",10));
out.close();
}
}
UnSerializable.java
package Sentiment.unserialize.demo01;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class UnSerializable {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream In = new ObjectInputStream(new FileInputStream("1.txt"));
Test o = (Test)In.readObject();
System.out.println(o);
}
}
運(yùn)行Serializable.java后便得到二進(jìn)制字節(jié)碼文件內(nèi)容

此時(shí)在運(yùn)行UnSerializable.java便得到了二進(jìn)制字節(jié)碼反序列化后的內(nèi)容

serialVersionUID
- 每個(gè)可序列化的類在序列化時(shí)都會(huì)關(guān)聯(lián)一個(gè)版本號(hào) , 這個(gè)版本號(hào)就是 serialVersionUID 屬性
- serialVersionUID 屬性必須通過 static final long 修飾符來修飾 。
- 如果可序列化的類未聲明 serialVersionUID 屬性 , 則 Java 序列化時(shí)會(huì)根據(jù)類的各種信息來計(jì)算默認(rèn)的 serialVersionUID 值 . 但是 Oracle 官方文檔強(qiáng)烈建議所有可序列化的類都顯示聲明 serialVersionUID 值 .
實(shí)例理解
在Test.java中定義serialVersionUID 其值為1
package Sentiment.unserialize.demo01;
import java.io.Serializable;
public class Test implements Serializable {
public static final long serialVersionUID = 1L; //定義serialVersionUID
private String name;
private int age;
public Test() {
}
public Test(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Test{" + "name='" + name + '\'' + ", age=" + age + '}';
}
}
此時(shí)運(yùn)行Serializable.java進(jìn)行序列化操作
運(yùn)行完畢后將serialVersionUID的值定義為2—>public static final long serialVersionUID = 2L;,在運(yùn)行UnSerializable.java會(huì)報(bào)錯(cuò)

Transient (瞬態(tài)變量)
Transient( 瞬態(tài)變量 )是一個(gè) Java 關(guān)鍵詞 , 它用于標(biāo)記類的成員變量在持久化到字節(jié)流時(shí)不要被序列化 ; 在通過網(wǎng)絡(luò)套接字流傳輸字節(jié)流時(shí) , transient 關(guān)鍵詞標(biāo)記的成員變量不會(huì)被序列化 。此為被static修飾的靜態(tài)變量也不參與序列化操作。
實(shí)例理解
將Test.java中的name和age變量前分別加上transient和static
package Sentiment.unserialize.demo01;
import java.io.Serializable;
public class Test implements Serializable {
public static final long serialVersionUID = 1L; //定義serialVersionUID
private transient String name; //加上transient
private static int age; //加上static
public Test() {
}
public Test(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Test{" + "name='" + name + '\'' + ", age=" + age + '}';
}
}
此時(shí)在執(zhí)行Serializable.java和UnSerializable.java,輸出結(jié)果:Sentiment—>null,10—>0

readObject()方法重寫
? 官方允許用戶在被序列化的類中重寫 readObject() 方法 , 重寫后的方法將負(fù)責(zé)在反序列化時(shí)重構(gòu)當(dāng)前類對(duì)象 . 用戶只需要在重寫的 readObject() 方法中實(shí)現(xiàn) defaultReadObject() 方法 , 就可以確保反序列化過程正常執(zhí)行 .
實(shí)例理解
實(shí)現(xiàn) defaultReadObject() 方法調(diào)用,并在Test類中重寫該方法,在進(jìn)行序列化和反序列化操作即可執(zhí)行命令
private void readObject(java.io.ObjectInputStream a) throws IOException, ClassNotFoundException{
a.defaultReadObject();
Runtime.getRuntime().exec("calc.exe");
}

總結(jié)
- 類想要進(jìn)行序列化操作,必須實(shí)現(xiàn)Serializable接口繼承
- 強(qiáng)烈建議定義serialVersionUID ,序列化、反序列化前后不要修改其值
- 被static、Transient修飾的屬性,不會(huì)進(jìn)行序列化操作
- readObject()方法重寫時(shí),需要實(shí)現(xiàn)defaultReadObject() 方法
以上就是Java序列化與反序列化的詳細(xì)內(nèi)容,更多關(guān)于Java序列化與反序列化的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
關(guān)于JavaEE匿名內(nèi)部類和Lambda表達(dá)式的注意事項(xiàng)
這篇文章主要介紹了關(guān)于JavaEE匿名內(nèi)部類和Lambda表達(dá)式的注意事項(xiàng),匿名內(nèi)部類顧名思義是沒有修飾符甚至沒有名稱的內(nèi)部類,使用匿名內(nèi)部類需要注意哪些地方,我們一起來看看吧2023-03-03
Spring高級(jí)之注解@PropertySource的原理
這篇文章主要介紹了Spring高級(jí)之注解@PropertySource的原理,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
使用Spring Initializr方式如何快速構(gòu)建Spring Boot項(xiàng)目
Spring lnitializr是一個(gè)Web應(yīng)用,它提供了一個(gè)基本的項(xiàng)目結(jié)構(gòu),能夠幫助我們快速構(gòu)建一個(gè)基礎(chǔ)的Spring Boot項(xiàng)目,本文分步驟講解如何使用Spring Initializr方式構(gòu)建Spring Boot項(xiàng)目,感興趣的朋友跟隨小編一起看看吧2023-08-08
Tomcat報(bào)錯(cuò):HTTP Status 500 (Wrapper cannot find servlet class)
這篇文章主要介紹了Tomcat報(bào)錯(cuò):HTTP Status 500 (Wrapper cannot find servlet class)解決辦法的相關(guān)資料,需要的朋友可以參考下2016-11-11
詳解如何讓Spring MVC顯示自定義的404 Not Found頁面
這篇文章主要介紹了詳解如何讓Spring MVC顯示自定義的404 Not Found頁面,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-10-10
java實(shí)現(xiàn)計(jì)算周期性提醒的示例
本文分享一個(gè)java實(shí)現(xiàn)計(jì)算周期性提醒的示例,可以計(jì)算父親節(jié)、母親節(jié)這樣的節(jié)日,也可以定義如每月最好一個(gè)周五,以方便安排會(huì)議2014-04-04
詳解spring boot整合JMS(ActiveMQ實(shí)現(xiàn))
本篇文章主要介紹了詳解spring boot整合JMS(ActiveMQ實(shí)現(xiàn)),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-10-10

