序列化 與 反序列化
序列化
Class ObjectOutputStream
java.lang.Object
java.io.OutputStream
java.io.ObjectOutputStream
實作接口
Closeable , DataOutput , Flushable , ObjectOutput , ObjectStreamConstants , AutoCloseable
可以通過使用流的檔案來實作對象的持久存儲
如果流是網絡套接字流,則可以在另一個主機上或另一個程序中重構對象(發個檔案到另一台電腦實作對象)
注意:
- 實作重構的對象必須實作 Java.io.Serializable 接口
- 重構對象的屬性也必須實作 Java.io.Serializable 接口
以上說明是實作重構對象的前提
構造方法
ObjectOutputStream()
ObjectOutputStream(OutputStream out)
方法 (方法自行API)
反序列化
Class ObjectInputStream
java.lang.Object
java.io.InputStream
java.io.ObjectInputStream
實作接口
Closeable , DataInput , ObjectInput , ObjectStreamConstants , AutoCloseable
ObjectInputStream用于恢複先前序列化的對象
構造方法
ObjectInputStream()
ObjectInputStream(InputStream in)
方法 (方法自行API)
序列化限制
指定對象部分屬性序列化
實作方式:
- 對象屬性用 transient 修飾符 限制屬性序列化
- 對象屬性用 static 修飾符 限制屬性序列化
- 對象實作 writeObject()方法 和 readObject()方法 進行對指定屬性進行執行個體化
注意:
方法3 ,writeObject()方法 和 readObject()方法 必須是 私有 無傳回,否則無效
//模闆
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
//寫
private void writeObject(ObjectOutputStream out) throws IOException
//讀
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
代碼執行個體
Main類 (寫入操作)
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
MySerializableUtil su = new MySerializableUtil();
//資料處理 ,儲存
People p = new People("柏竹" , 20 , null);
List<String> childrenName = new ArrayList<>();
childrenName.add("黑貓");
childrenName.add("大鲸");
childrenName.add("白兔");
HaveAll haveAll = new HaveAll(7654321 , "網球" , 3);
haveAll.setChildrenName(childrenName);
p.setHaveAll(haveAll);
System.out.println("原始資料 : "+ p);
//資料 序列化
String fileName = "Date.txt";
try {
MySerializableUtil.mySerializableUtil(p , fileName);
System.out.println("Serialization OK!");
} catch (Exception e) {
e.printStackTrace();
}
//讀取
System.out.println("讀資料 : ");
Object o = su.myDeserialize(fileName);
System.out.println(o);
}
}
/*
原始資料 : People{name='柏竹', age=20, haveAll=HaveAll{money=7654321, house='網球', childrenNum=3}}
調用 writeObject() 限制!!!
Serialization OK!
讀資料 :
調用 readObject() !!!
People{name='柏竹', age=20, haveAll=HaveAll{money=0, house='網球', childrenNum=3}}
*/
Input類 (讀檔案資料)(用于在别的地方讀取對象)
public class Input {
public static void main(String[] args) {
MySerializableUtil su = new MySerializableUtil();
Object o = su.myDeserialize("Date.txt");
System.out.println(o);
}
}
MySerializableUtil類 (操作工具)
import java.io.*;
/**
* 序列化 與 序列化 工具類
*/
public class MySerializableUtil {
/**
* 序列化
* @param data 資料
* @param fileName 位元組輸出流
*/
public static void mySerializableUtil(Object data , String fileName){
try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(fileName))) {
oos.writeObject(data);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 反序列化
* @param fileName 位元組輸入流
* @return 傳回擷取的對象
*/
public static Object myDeserialize(String fileName){
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(fileName))) {
return ois.readObject();
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
People類 (存儲對象)
import java.io.IOException;
import java.io.Serializable;
import java.io.Serializable;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
* 實作Serializable接口
*/
public class People implements Serializable {
String name;
//年齡不能序列化
static int age;
/**人的明細*/
HaveAll haveAll;
//指定對象序列化
private void writeObject(ObjectOutputStream out) throws IOException {
System.out.println(" 調用 writeObject() 限制!!!");
out.writeObject(name);
out.writeObject(haveAll);
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException{
System.out.println(" 調用 readObject() !!!");
name =(String) in.readObject();
haveAll = (HaveAll) in.readObject();
}
public People() {
}
public People(String name , int age , HaveAll haveAll) {
this.name = name;
this.age = age;
this.haveAll = haveAll;
}
public void setHaveAll(HaveAll haveAll) {
this.haveAll = haveAll;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public HaveAll getHaveAll() {
return haveAll;
}
@Override
public String toString() {
return "People{" +
"name='" + name + '\'' +
", age=" + age +
", haveAll=" + haveAll +
'}';
}
}
HaveAll類 (存儲PeoPle對象中的對象)
import java.io.Serializable;
import java.util.List;
public class HaveAll implements Serializable {
// 餘額 & 愛好 & 已有的孩子 & 孩子名字集合
// 餘額不能序列化對象
private transient long money;
String house;
int childrenNum;
List<String> childrenName;
//不多寫了
public HaveAll() { }
public HaveAll(long money , String house ,int childrenNum) {
this.money = money;
this.house = house;
this.childrenNum = childrenNum;
}
public List<String> getChildrenName() {
return childrenName;
}
public void setChildrenName(List<String> childrenName) {
this.childrenName = childrenName;
}
public void setMoney(long money) {
this.money = money;
}
public void setHouse(String house) {
this.house = house;
}
public void setChildrenNum(int childrenNum) {
this.childrenNum = childrenNum;
}
public long getMoney() {
return money;
}
public String getHouse() {
return house;
}
public int getChildrenNum() {
return childrenNum;
}
@Override
public String toString() {
return "HaveAll{" +
"money=" + money +
", house='" + house + '\'' +
", childrenNum=" + childrenNum +
'}';
}
}
Externalizable接口 序列化
繼承接口
Serializable
實作類
ActivationDataFlavor , DataFlavor , MimeType , MLet , PrivateMLet
Externalizable接口 也能實作 序列化 和 反序列化 ,因繼承 Serializable接口。
使用該接口需要定義
writeExteranl()
、
readExternal()
抽象方法才可以實作序列化與反序列化
//模闆
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
//寫
public void writeExternal(ObjectOutputStream out) throws IOException
//讀
public void readExternal(ObjectInputStream in) throws IOException, ClassNotFoundException
實作方式:
在以上代碼中的 People類 更改
import java.io.IOException;
import java.io.Serializable;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
* 實作Serializable接口
*/
public class People implements Externalizable {
String name;
//年齡不能序列化
static int age;
/**人的明細*/
HaveAll haveAll;
//指定對象序列化
public void writeExternal(ObjectOutputStream out) throws IOException {
System.out.println(" 調用 writeObject() 限制!!!");
out.writeObject(name);
out.writeObject(haveAll);
}
public void readExternal(ObjectInputStream in) throws IOException, ClassNotFoundException{
System.out.println(" 調用 readObject() !!!");
name =(String) in.readObject();
haveAll = (HaveAll) in.readObject();
}
//·····省略
}