java --序列化

#1.序列化與反序列化的概念
將對象轉換爲字節序列的過程稱爲對象的序列化。
反過來,將字節序列恢復成對象的過程稱爲對象的反序列化。
#2.爲何要將對象序列化?
2.1當咱們須要將內存中的對象保存到一個文件中/數據庫中的時候
一般咱們須要將某些對象進行序列化,讓它離開內存空間,入駐物理硬盤,以便長期保存,須要的時候在調取它。例如:緩存,咱們須要將緩存存儲起來,須要的時候再將它取出來。
2.2須要在網絡上傳送對象的時候
當兩個進程在進行遠程通訊時,彼此時間須要發送數據,不管哪一種類型的數據,都會以二進制序列的形式在網絡上傳送。
#3.如何實現對象序列化?
很簡單,將須要序列化的類實現Serializable接口便可,Serializable接口中沒有任何方法。將它理解爲一個標記,即代表這個類能夠序列化。
#4.實現序列化原理
java.io.ObjectOutputStream表示對象輸出流,writeObject(Object obj)方法將指定對象obj寫入一個輸出流中,即對該對象進行序列化。
java.io.ObjectInputStream表示對象輸入流,readObject()方法從ObjectInputStream讀取字節序列,再將它們反序列化成爲一個對象,並將其返回。
只有實現了Serializable接口的類才能被序列化。對象序列化步驟:
1>建立一個對象輸出流,即ObjectOutputStream,它能夠包裝一個目標輸出流,例如文件輸出流。
2>調用writeObject(Object obj)方法,參數爲obj
對象反序列化過程:
1>建立一個對象輸入流,即ObjectInputStream,它能夠包裝一個源輸入流,例如文件輸入流。
2>調用readObject()方法讀取對象
#5.實例
5.1 定義一個User類並實現Serializablejava

public class User implements Serializable{
	//序列化id
	private static final long serialVersionUID = 1L;

	private Integer id;
        private String name;
}

5.2序列化與反序列化User對象spring

public class TestSerializable {
	public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
		//序列化對象
		SerializeUser();
		//反序列化
		User user = DeSerializeUser();
		System.out.println(user);
	}
}

序列化對象代碼數據庫

/**
	 * 序列化User對象
	 * 1>建立一個對象輸出流,即ObjectOutputStream,它能夠包裝一個目標輸出流,例如文件輸出流。  
	 * 2>調用writeObject(Object obj)方法,參數爲obj  
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 */
	private static void SerializeUser() throws InstantiationException, IllegalAccessException{
		
		//運用反射建立User對象
		User user = new User();
		try {
			Class<?> clazz = Class.forName("com.test.spring.bean.User");
			user = (User) clazz.newInstance();
			user.setId(1001);
			user.setName("張三");
		} catch (ClassNotFoundException e1) {
			System.out.println("沒有找到該類");
			e1.printStackTrace();
		}
		//建立對象輸出流
		//將User對象序列化,並存儲到E盤的Test文件下User.txt文件中
		ObjectOutputStream oos = null;
		try {
			oos = new ObjectOutputStream(new FileOutputStream(new File("E:\\Test\\User.txt")));
			oos.writeObject(user);
			System.out.println("對象序列化成功");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			try {
				oos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

反序列化代碼緩存

/**
	 * 反序列化User對象
	 * 1>建立一個對象輸入流,即ObjectInputStream,它能夠包裝一個源輸入流,例如文件輸入流。  
	 * 2>調用readObject()方法讀取對象  
	 * @throws ClassNotFoundException 
	 */
	private static User DeSerializeUser() throws ClassNotFoundException{
		//new方式建立對象
		User user = new User();
		ObjectInputStream ois = null;
		try {
			ois = new ObjectInputStream(new FileInputStream(new File("E:\\Test\\User.txt")));
			user = (User) ois.readObject();
			System.out.println("對象反序列化成功");
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			try {
				ois.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return user;
	}

#6.serialVersionUID
serialVersionUID是序列化版本號,全部實現Serializable接口的類都須要有一個表示序列化版本標識符。
那這個serialVersionUID有什麼用呢?
1.咱們去掉User類中的serialVersionUID
輸入圖片說明
2.在序列化這個類
輸入圖片說明
3.在User類中添加新的屬性
輸入圖片說明
4.再反序列化User類
報錯信息以下網絡

java.io.InvalidClassException: com.test.spring.bean.User; local class incompatible: stream classdesc serialVersionUID = 5057804141597769629, local class serialVersionUID = -2824417979782532292

反序列化的過程當中出現問題,報錯是stream classdesc serialVersionUID與local class serialVersionUID不一致。
在User類中,若是咱們沒有指定serialVersionUID,則java編譯器會自動給該類添加一個serialVersionUID;因爲沒有顯式的指定serialVersionUID,全部咱們修改了User類以後,編譯器又會給咱們指定一個serialVersionUID,這就出現了兩個序列化版本號不一致的錯誤。
接着測試下有serialVersionUID的狀況
1.加上serialVersionUID
2.序列化對象
3.修改對象字段
4.直接反序列化對象
測試了(假設新增屬性爲age),證實能夠反序列化成功,結果以下測試

對象反序列化成功
User [id=1001, name=張三, age=null]
相關文章
相關標籤/搜索