對象流
- 寫對象數據:
對象數據 ——>字節數據 對象的序列化 讀取對象數據:
字節數據 ——>對象數據 對象的反序列化Serializable接口
此接口中沒有任何內容,此接口是一個標誌接口,此接口通常就是用於表示某個類的對象是可序列化的
如果一個對象想要被序列化和反序列化,前提:該對象所屬的類必須實現Serializable 接口
將對象寫入文件中去,到底是對象的什麼數據寫到了文件中?
此對象所屬類的信息,對象中的數據,其他信息
Studnet類
public class Student implements Serializable{
private int id;
private String name;
private int age;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(int id, String name, int age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
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 "Student [id=" + id + ", name=" + name + ", age=" + age + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (id != other.id)
return false;
return true;
}
}
寫對象數據
/**
* 向文件中寫入Student對象數據
* @author adminitartor
*
*/
public class WriteObectDemo {
public static void main(String[] args) throws FileNotFoundException, IOException {
//創建流對象
ObjectOutputStream oos = new
ObjectOutputStream(new
FileOutputStream("oos.txt"));
//寫數據
Student student = new Student(1, "tom", 23);
oos.writeObject(student);
//釋放資源
oos.close();
}
}
讀取對象數據
/**
* 讀取文件中的字節數據還原成對象數據
* @author adminitartor
*
*/
public class ReadObjectDemo {
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
//創建流對象
ObjectInputStream ois = new
ObjectInputStream(new
FileInputStream("oos.txt"));
//讀取數據
Student stu = (Student)ois.readObject();
System.out.println(stu);
//釋放資源
ois.close();
}
}
對象序列化:
- 對象是存在於內存中的。有時候我們需要將對象保存到硬盤上,又有時我們需要將對象傳輸到另一臺計算機上等等這樣的操作。這時我們需要將對象轉換爲一個字節序列,而這個過程就稱爲對象序列化
反序列化:
- 相反,我們有這樣一個字節序列需要將其轉換爲對應的對象,這個過程就稱爲對象的反序列化。
反序列化的機制:
- 當一個類實現了Serializable接口後,編譯器會提示應當添加一個常量:serialVersionUID,這個常量標識當前類的序列化版本號.若不指定,編譯器在編譯當前類時會根據當前類的結構計算生成版本號,但是隻要類的結構發生了變化,那麼版本號就會改變.版本號決定着一個對象是否可以反序列化成功.
當對象輸入流在將一個對象進行反序列化時會檢查該對象的版本號與當前程序中這個類的版本號是否一致?
若一致:反序列化成功,若當前類發生了改變,那麼則還原依
然存在的屬性.
*若不一致,則反序列化方法readObject會拋出異常.
方法:
寫對象數據 -writerObject(Object)
讀取對象數據 -readObject() -Object
向文件中寫入Student對象數據
//創建流對象
ObjectOutputStream oos = new
ObjectOutputStream(new
FileOutputStream("oos.txt"));
//寫數據
Student student = new Student(1, "tom", 23);
oos.writeObject(student);
//釋放資源
oos.close();
讀取文件中的字節數據還原成對象數據
//創建流對象
ObjectInputStream ois = new
ObjectInputStream(new
FileInputStream("oos.txt"));
//讀取數據
Student stu = (Student)ois.readObject();
System.out.println(stu);
//釋放資源
ois.close();
如果對一個類添加屬性或減少屬性,對已經寫好的對象進行反序列化,出現什麼問題?如何解決?
出現的問題: 反序列化失敗,拋出異常
解決方案:在實現Serializable接口的類中,手動生成序列版本號
public class Student implements Serializable{
/**
*
*/
private static final long serialVersionUID = 6711298969568631630L;
private int id;
private String name;
private int age;
private String gender;
案列:
類:person
屬性:id name age desc
要求: 將person 對象寫入文件中時,desc 屬性的值不 寫入
解決辦法:使用transient關鍵字
public class Person implements Serializable {
/**
*
*/
private static final long serialVersionUID = 403295796195916326L;
private int id;
private String name;
private int age;
private transient String desc;
將Person對象寫入文件,對象中的desc屬性值
不寫入,讀取文件中的數據並打印到控制檯
//寫對象數據
//創建流對象
// ObjectOutputStream oos = new
// ObjectOutputStream(new
// FileOutputStream("person.txt"));
// //寫Person對象
// Person person = new Person(12, "jack", 23, "聰明的,胖的");
// oos.writeObject(person);
//
// //釋放資源
// oos.close();
/*
* 將person.txt中的對象數據還原
*/
//創建流對象
ObjectInputStream ois = new
ObjectInputStream(new
FileInputStream("person.txt"));
//讀取對象數據 - 反序列化
Person per = (Person)ois.readObject();
System.out.println(per);
//釋放資源
ois.close();
transient關鍵字:
用於修飾類中的成員變量
當一個屬性被transient修飾後,該屬性在進行對象序列化時其值會被忽略.
當一個對象是可序列化是,如果內部的成員有別的對象,那麼,作爲成員的其他對象一定也是可序列化的。
Person類
public class Person implements Serializable {
/**
*
*/
private static final long serialVersionUID = 403295796195916326L;
private int id;
private String name;
private int age;
private transient String desc;
Worker類
public class Worker implements Serializable {
/**
*
*/
private static final long serialVersionUID = 3406471866652587638L;
private Person person;
private String workId;
測試類
public class WorkerDemo {
public static void main(String[] args) throws FileNotFoundException, IOException {
/*
* 將Worker對象寫入文件中去
*/
ObjectOutputStream oos = new
ObjectOutputStream(new
FileOutputStream("worker.txt"));
Person per = new Person(1001, "tom", 33, null);
Worker worker = new Worker(per, "1213");
oos.writeObject(worker);
oos.close();
}
}
反序列化原理圖: