物件流ObjectInputStream和ObjectOutputStream
引言
-
看一個需求
- 將int num=100這個 int 資料保存到檔案中,注意不是 100 數字,而是 int 100,并且,能夠從檔案中直接恢復 int 100;
- 將Dog dog = new Dog("小黃",3)這個dog物件保存到檔案中,并且能夠從檔案恢復;
- 上面的要求,就是能夠將 基本資料型別 或者 物件 進行 序列化 和 反序列化 操作;
-
序列化和反序列化
- 序列化就是在保存資料時,保存資料的值和資料型別;
- 反序列化就是在恢復資料時,恢復資料的值和資料型別;
- 需要讓某個物件支持序列化機制,則必須讓其類是可序列化的,為了讓某個類是可序列化的,該類必須實作如下兩個介面之一:
- Serializable:這是一個標記介面,沒有方法
- Externalizable:該介面有方法需要實作,因此我們一般實作上面的Serializable
-
基本介紹
- 功能:提供了對基本型別或物件型別的序列化和反序列化的方法;
- ObjectOutputStream 提供 序列化功能;
- ObjectInputStream 提供 反序列化功能;
ObjectOutputStream
代碼演示:
import java.io.*;
/**
* @author: 86199
* @date: 2023/5/5 21:51
* @description: 演示ObjectOutputStream的使用,完成資料的序列化
*/
public class ObjectOutputStream_ {
public static void main(String[] args) throws IOException {
//序列化后,保存的檔案格式,不是純文本,而是按照序列化自己規定的格式來保存
String filePath = "e:\\data.dat";
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));
//序列化資料到 e:\data.dat
oos.writeInt(100);//int -> Integer(實作了 Serializable)
oos.writeBoolean(true);//boolean -> Boolean(實作了 Serializable)
oos.writeChar('a');//char -> Character(實作了 Serializable)
oos.writeDouble(9.5);//double -> Double(實作了 Serializable)
oos.writeUTF("紅樓夢");//String
//保存一個dog物件
oos.writeObject(new Dog("旺財",10));
//關閉流
oos.close();
System.out.println("資料保存完畢(序列化形式)");
}
}
Dog類代碼:
import java.io.Serializable;
/**
* @author: 86199
* @date: 2023/5/5 23:09
* @description:
*/
//如果需要序列化某個物件,實作 Serializable
public class Dog implements Serializable {
private String name;
private int age;
//序列化物件時,默認將里面所有的屬性都進行序列化,但除了static或transient修飾的成員
private static String nation;
private transient String color;
//序列化物件化時,要求里里面的屬性的型別也必須實作序列化介面
private Master master = new Master();
//serialVersionUID 序列化的版本號,可以提高兼容性
//這樣對該類進行修改后,進行序列化或者反序列化時就不會認為該類
//是全新的類,只是進行了版本更新
//物件的序列化反序列化是根據序列化版本id進行的,沒有顯式得寫出來會默認根據類的屬性和方法分配一個,導致物件序列化入庫之后,若類被修改,反序列化將會報錯,所以顯式加上序列化版本id,避免反序列化報錯
private static final long serialVersionUID = 1L;
public Dog(String name, int age, String nation, String color) {
this.name = name;
this.age = age;
this.color = color;
this.nation = nation;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
", color = '" + color + '\'' +
", nation = '" + nation + '\'' +
'}' + " " + master;
}
}
ObjectInputStream
代碼演示:
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import com.hsp.outputstream_.Dog;
/**
* @author: 86199
* @date: 2023/5/5 22:28
* @description: 演示ObjectInputStream的使用,完成資料的反序列化
*/
public class ObjectInputStream_ {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//指定反序列化的檔案
String filePath = "e:\\data.dat";
//反序列化時,要保證和序列化時的資訊是一致的,若被序列化的資料的類資訊有改動,此時直接反序列化自然會出錯,需要重新序列化資料(如果Dog加了serialVersionUID就不會報錯)
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath));
//讀取
//讀取(反序列化)的順序需要和保存資料(序列化)的順序一致,否則會出現例外
System.out.println(ois.readInt());
System.out.println(ois.readBoolean());
System.out.println(ois.readChar());
System.out.println(ois.readDouble());
System.out.println(ois.readUTF());
Object dog = ois.readObject();//底層Object -> Dog
System.out.println("運行型別 = " + dog.getClass());
System.out.println("dog資訊 = " + dog);
//要想使用 我們這個反序列化來的Dog物件,還得使Dog可以在這被參考,然后向下轉型
//1. 如果我們希望呼叫Dog的方法,需要向下轉型
//2. 需要我們將Dog類的定義,放在可以參考的位置
Dog dog2 = (Dog)dog;
System.out.println(dog2.getName());
//關閉流
ois.close();
}
}
/*運行結果
100
true
a
9.5
紅樓夢
運行型別 = class com.hsp.outputstream_.Dog
dog資訊 = Dog{name='旺財', age=10, color = 'null', nation = 'null'} com.hsp.outputstream_.Master@66a29884
旺財
*/
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/554348.html
標籤:其他
上一篇:C++面試八股文:如何在堆上和堆疊上分配一塊記憶體?
下一篇:返回列表