天天看點

Java 實作 序列化 與 反序列化序列化 與 反序列化Externalizable接口 序列化

序列化 與 反序列化

序列化

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)

序列化限制

指定對象部分屬性序列化

實作方式:

  1. 對象屬性用 transient 修飾符 限制屬性序列化
  2. 對象屬性用 static 修飾符 限制屬性序列化
  3. 對象實作 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();
    }
    
   //·····省略
}