轉自:http://blog.csdn.net/chx10051413/article/details/40784667
http://www.cnblogs.com/baoendemao/p/3804797.html
Java 中如何序列化一個對象
我們都知道java 中無法保存一個對象到文本文件中,但是當我們有這種需求的時候,我們可以通過java 的序列化功能把當前對象的一些屬性以二進制的形式保存到文件中。當我們需要這個對象的時,只需要從二進制文件中還原為保存前的對象即可。從這里我們可以得到啟發,如果想把機器A 上的一個Student 對象發送到機器B 上,我們可以把Student 對象序列化成二進制,然后把該二進制發送給機器B,機器B 就可以根據二進制數據還原成Student 對象了,這就變相的實現了在機器間傳播對象的功能。
寫入序列化數據到文件中,主要是兩個對象,一個對象是FileOutputStream 對象,一個是ObjectOutputStream 對象,ObjectOutputStream 負責向指定的流中寫入序列化的對象。當從文件中讀取序列化數據時,主要需要兩個對象,一個是FileInputStream ,一個是ObjectInputStream 對象,ObjectInputStream 負責從指定流中讀取序列化數據並還原成序列化前得對象。另外,序列化的讀取數據與寫入的順序相同,比如我們序列化時先寫入數據A ,再寫入B ,最后寫入C ;那么我們再讀取數據的時候,讀取到的第一個數據為A ,讀取到的第二個數據為B ,最后讀取到的數據為C ,即:先寫入先讀取的原則。
在序列化一個對象的時候,這個對象必須實現java.io.Serializable 接口, Serializable 接口中不含任何方法,這個可以理解為聲明該對象是可以序列化的方法吧。當我們在序列化一個對象時,有些屬性我們不想序列化(可以減少數據量),那么我們可以聲明該屬性為瞬間態(用transient 關鍵字聲明)。另外,靜態字段也是不會被序列化的。
當我們在序列化一個對象時,如果該對象沒有覆寫writeObject 或者readObject 方法,那么系統將采用默認的方法進行序列化,如果序列化對象中有這兩個方法,則采用對象中的這兩個方法進行序列化。至於如何找到的這兩個方法,通過代碼我們可以跟蹤到是根據反射的方式進行判斷對象是否覆寫這兩個方法。另外,這兩個方法在對象中是
我們所說的流,都是針對內存說的,比如為什么打印到屏幕上就是System.out.println();而從屏幕等待用戶輸入的卻是System.in呢?因為對於內存來說,把字符串打印到屏幕上是從內存流向屏幕這個顯示器的,也就是輸出,而從屏幕等待用戶輸入呢?就是等待鍵盤將字符輸入到內存中。
所以,你根本就不用死記硬背,當你遇到IO的時候,就想兩件事,第一,我的內存是中心,第二看看流的方向(矢量)!
好吧,那么往硬盤上寫文件是out還是in呢?別一看到“寫”文件你就說in,那是望文生義,你看,寫文件的流向,是 內存---------->硬盤 內存為中心,到硬盤,OK 用out 那么就是FileOutputStream、BufferedOutputStream 等等
那讀文件呢?是 內存<---------------硬盤 那么就是in了 , 看清楚數據的流向就OK!
那我訪問網絡,看網頁是什么呢 網絡--------------->內存 是in 因為我們訪問頁面是要抓取該頁面得一個html文件,那我要是在網絡上輸入帳號密碼登陸呢? 是不是內存的東西要寫到該服務器上呢,所以當然是out了!
同樣socket編程用到更多的IO,這里分別用Server(服務器端)和Client(客戶端)來說明
Server: 遇到請求,網絡----->內存 IN 服務器應答, 內存------->網絡 OUT
----------------------------------------------------------------------------------------------
Client: 請求服務, 內存----->網絡 OUT 服務器應答, 網絡------->內存 IN
被搞糊塗了?那么你先別想太多,只是想是內存的數據出去了就是out 外設的東西到內存了就IN了
Java 串行化技術可以使你將一個對象的狀態寫入一個Byte 流里,並且可以從其它地方把該Byte 流里的數據讀出來,重新構造一個相同的對象。這種機制允許你將對象通過網絡進行傳播,並可以隨時把對象持久化到數據庫、文件等系統里。Java的串行化機制是RMI、EJB等技術的技術基礎。用途:利用對象的串行化實現保存應用程序的當前工作狀態,下次再啟動的時候將自動地恢復到上次執行的狀態。
序列化就是一種用來處理對象流的機制,所謂對象流也就是將對象的內容進行流化。可以對流化后的對象進行讀寫操作,也可將流化后的對象傳輸於網絡之間。序列化是為了解決在對對象流進行讀寫操作時所引發的問題。
序列化的實現:將需要被序列化的類實現Serializable接口,然后使用一個輸出流(如:FileOutputStream)來構造一個ObjectOutputStream(對象流)對象,接着,使用ObjectOutputStream對象的writeObject(Object obj)方法就可以將參數為obj的對象寫出(即保存其狀態),要恢復的話則用輸入流。
2、串行化的特點:
(1)如果某個類能夠被串行化,其子類也可以被串行化。如果該類有父類,則分兩種情況來考慮,如果該父類已經實現了可串行化接口。則其父類的相應字段及屬性的處理和該類相同;如果該類的父類沒有實現可串行化接口,則該類的父類所有的字段屬性將不會串行化。
(2)聲明為static和transient類型的成員數據不能被串行化。因為static代表類的狀態, transient代表對象的臨時數據;
(3)相關的類和接口:在java.io包中提供的涉及對象的串行化的類與接口有ObjectOutput接口、ObjectOutputStream類、ObjectInput接口、ObjectInputStream類。
(1)ObjectOutput接口:它繼承DataOutput接口並且支持對象的串行化,其內的writeObject()方法實現存儲一個對象。ObjectInput接口:它繼承DataInput接口並且支持對象的串行化,其內的readObject()方法實現讀取一個對象。
(2)ObjectOutputStream類:它繼承OutputStream類並且實現ObjectOutput接口。利用該類來實現將對象存儲(調用ObjectOutput接口中的writeObject()方法)。ObjectInputStream類:它繼承InputStream類並且實現ObjectInput接口。利用該類來實現讀取一個對象(調用ObjectInput接口中的readObject()方法)。
對於父類的處理,如果父類沒有實現串行化接口,則其必須有默認的構造函數(即沒有參數的構造函數)。否則編譯的時候就會報錯。在反串行化的時候,默認構造函數會被調用。但是若把父類標記為可以串行化,則在反串行化的時候,其默認構造函數不會被調用。這是為什么呢?這是因為Java 對串行化的對象進行反串行化的時候,直接從流里獲取其對象數據來生成一個對象實例,而不是通過其構造函數來完成。
import java.io.*;
public class Cat implements Serializable {
private String name;
public Cat () {
this.name = "new cat";
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public static void main(String[] args) {
Cat cat = new Cat();
try {
FileOutputStream獲得一個文件流,ObjectOutputStream鏈接對象和文件流,通過writeObject方法把對象寫到硬盤上面,從內存中的對象寫到硬盤,故是OUT流
FileOutputStream fos = new FileOutputStream("catDemo.out");
ObjectOutputStream oos = new ObjectOutputStream(fos);
System.out.println(" 1> " + cat.getName());
cat.setName("My Cat");
oos.writeObject(cat);
oos.close();
} catch (Exception ex) { ex.printStackTrace(); }
try {
把硬盤文件中的對象寫到內存,故是IN流
FileInputStream fis = new FileInputStream("catDemo.out");
ObjectInputStream ois = new ObjectInputStream(fis);
cat = (Cat) ois.readObject();
System.out.println(" 2> " + cat.getName());
ois.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}//writeObject和readObject本身就是線程安全的,傳輸過程中是不允許被並發訪問的。所以對象能一個一個接連不斷的傳過來
最后再給出一個連接:http://blog.csdn.net/lulei1217/article/details/50527824 關於lo的文章,以后備用