**序列化和反序列化的概念
把對象轉化爲字節序列的過程稱之爲對象的序列化
反之,稱之爲反序列化
serialVersionUID的作用
如果沒有爲指定的class配置serialVersionUID,那麼java編譯器會自動給這個class進行一個摘要算法,類似於指紋算法,只要這個文件有任何改動,得到的UID就會截然不同的,可以保證在這麼多類中,這個編號是唯一的。所以,由於沒有顯指定 serialVersionUID,編譯器又爲我們生成了一個UID,當然和前面保存在文件中的那個不會一樣了,於是就出現了2個序列化版本號不一致的錯誤。因此,只要我們自己指定了serialVersionUID,就可以在序列化後,去添加一個字段,或者方法,而不會影響到後期的還原,還原後的對象照樣可以使用,而且還多了方法或者屬性可以用。
靜態變量的序列化
序列化並不保存靜態變量的狀態
Transient關鍵字
transient關鍵字表示指定屬性不參與序列化
父子類問題
如果父類沒有實現序列化,而子類實現列序列化。那麼父類中的成員沒辦法做序列化操作
序列化的存儲規則
對同一個對象進行多次寫入,打印出的第一次存儲結果和第二次存儲結果,只多了5個字節的引用關係。
並不會導致文件累加
序列化實現深度克隆
淺拷貝(淺複製、淺克隆):被複制對象的所有變量都含有與原來的對象相同的值,而所有的對其他對象的引用仍然指向原來的對象。換言之,淺拷貝僅僅複製所拷貝的對象,而不復制它所引用的對象。
深拷貝(深複製、深克隆):被複制對象的所有變量都含有與原來的對象相同的值,除去那些引用其他對象的變量。那些引用其他對象的變量將指向被複制過的新對象,而不再是原有的那些被引用的對象。換言之,深拷貝把要複製的對象所引用的對象都複製了一遍
下面是將一個對象進行序列化和反序列化的例子:
public class Person implements Serializable{
private static final long serialVersionUID = -2572627257192440740L;
private String name;
private int age;
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;
}
}
public class SerializeDemo {
public static void main(String[] args) {
// 序列化操作
SerializePerson();
//反序列化操作
Person person=DeSerializePerson();
System.out.println(person);
}
private static void SerializePerson(){
try {
ObjectOutputStream oo=new ObjectOutputStream(new FileOutputStream(new File("person")));
Person person=new Person();
person.setAge(18);
person.setName("test");
oo.writeObject(person);
oo.flush();
System.out.println("序列化成功: "+new File("person").length());
oo.close();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
private static Person DeSerializePerson(){
ObjectInputStream ois= null;
try {
ois = new ObjectInputStream(new FileInputStream(new File("person")));
Person person=(Person)ois.readObject();
return person;
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
總結
1.在java中,只要一個類實現了java.io.Serializable接口,那麼它就可以被序列化
2.通過ObjectOutputStream和ObjectInputStream對對象進行序列化合反序列化操作
3. 對象是否允許被反序列化,不僅僅是取決於對象的代碼是否一致,同時還有一個重要的因素(UID)
4. 序列化不保存靜態變量
5. 要想父類對象也參與序列化操作,那麼必須要讓父類也實現Serializable接口
6. Transient關鍵字,主要是控制變量是否能夠被序列化。如果沒有被序列化的成員變量反序列化後,會被設置成初始值,比如String -> null
7. 通過序列化操作實現深度克隆