天天看點

java中序列化和反序列化

Serializable(序列化)是java中的一個接口,通過讓類實作這個接口,可以儲存對象的狀态。序列化有以下幾個知識點:

1. 序列化隻會儲存對象的變量資訊,不會儲存對象的方法資訊

2. 如果父類實作了Serializable接口,則子類預設實作了Serializable接口,即使子類沒有聲明也一樣。

3. 當對象被序列化時,如果對象包含了對其他對象的引用,則其他對象也會被序列化。比如說一個類A裡面有一個變量 b 是引用B類的一個對象,則當A類的對象a被序列化時,b對象也會被序列化。

4. 當對象被序列化時,如果對象中有成員變量不能被序列化,則會抛出異常

5. 靜态變量不會被序列化,因為靜态變量屬于類而不屬于對象。

6. 有transient标記的變量不會被序列化

有了序列化之後就會有反序列化。反序列化是将序列化儲存的對象的狀态還原出來。其有以下幾個知識點:

1. 反序列化不會調用對象的構造函數

2. 反序列化是在堆中建立對象并嘗試還原儲存的對象的狀态,而不是對原有對象的操作

3. 當原有對象中有transient辨別的不序列化變量時,反序列化時會使用其預設值。主資料類型(int , long , double, boolean, char ···)會被指派為預設值(int 為0, boolean 為 false),而引用對象則會被指派為null。

4. 當原有對象中有靜态變量時,反序列化時其值等于最近對該變量操作所得的值。比如說程式初始化該靜态變量為1,在反序列化之前又對該靜态變量指派為100,那麼反序列化之後該靜态變量的值就是100而不是1.

下面通過一個簡單的小程式來說明靜态變量和transient不會被序列化

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

class A implements Serializable
{
	public static int staticInt = 3; // 靜态變量不會被序列化
	private String string;
	private transient int num = 1;  // 這個變量不會被序列化
	
	A(String s, int num)
	{
		string = s;
		this.num = num;
	}
	
	public int getNum()
	{
		return num;
	}

	public void setNum(int num)
	{
		this.num = num;
	}

	public String getString()
	{
		return string;
	}
	public void setString(String string)
	{
		this.string = string;
	}
	
}

public class Test
{
	public static void printA(A a, String name)
	{
		System.out.println("----------" + name + "-------------");
		System.out.println("string: " + a.getString());
		System.out.println("num: " + a.getNum());
		System.out.println("staticInt: " + a.staticInt);
	}
	
	public static void main(String[] argv)
	{
		// 建立兩個A對象
		A a = new A("hello", 10);
		A aa = new A("world", 20);
		
		// 輸出其内容
		System.out.println("-------------before Serializable--------------");
		printA(a, "a");
		printA(aa, "aa");
		
		// 對兩個A對象進行序列化
		try
		{
			ObjectOutputStream ous = new ObjectOutputStream(new FileOutputStream("a.txt"));
			ous.writeObject(a);
			ous.writeObject(aa);
			ous.close();
		}
		catch (FileNotFoundException e)
		{
			e.printStackTrace();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
		
		// 序列化後改變對象 a 和 aa 的值,并輸出
		a.setString("hello world!");
		a.setNum(30);
		aa.setString("world hello");
		aa.setNum(40);
		A.staticInt = 100;
		System.out.println("-------------after Serializable, change a and aa--------------");
		printA(a, "a");
		printA(aa, "aa");
		
		// 反序列化并輸出結果
		try
		{
			ObjectInputStream ois = new ObjectInputStream(new FileInputStream("a.txt"));
			A aNew = (A) ois.readObject();
			A aaNew = (A) ois.readObject();
			
			System.out.println("--------------deserializable--------------");
			printA(a, "a");
			printA(aa, "aa");
			printA(aNew, "aNew");
			printA(aaNew, "aaNew");
			
			ois.close();
		}
		catch (FileNotFoundException e)
		{
			e.printStackTrace();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
		catch (ClassNotFoundException e)
		{
			e.printStackTrace();
		}
	}
}
           

程式運作結果如下

java中序列化和反序列化
java中序列化和反序列化