Java序列化與反序列化

在Java中,序列化其實有兩個用處,保存和傳送數據。

保存數據:將對象的狀態持久保存在存儲媒體(數據庫或文件系統)上,以後可以重新創建精確的副本。

Java允許我們在內存中創建可複用的Java對象,但一般情況下,只有當JVM處於運行時,這些對象纔可能存在,也就是說,如果JVM停止了,原本佔用的內存被釋放,對象自然也不復存在。如果要求在JVM停止運行之後能夠保存指定的對象,並在將來重新讀取被保存的對象,Java對象序列化就能夠實現。使用Java對象序列化,在保存對象時,會把其狀態保存爲一組字節,以後如果要用到這個對象,就可以通過反序列化,將這些字節組裝成對象。注意,對象序列化保存的是對象的"狀態",即它的成員變量,而靜態變量屬於類的狀態,由此可知,對象序列化不會關注類中的靜態變量。

傳送數據:將對象從一個應用程序域發送到另一個應用程序域中(遠程調用RMI)。

當兩個進程在進行遠程通信時,彼此可以發送各種類型的數據。無論是何種類型的數據,都會以二進制序列的形式在網絡上傳送。發送方需要把這個對象轉換爲字節序列,才能在網絡上傳送;接收方則需要把字節序列再恢復爲對象,而不是通過構造方法新建一個新的對象再賦予原來的值。將對象轉化爲流的過程其實就是序列化(Serialization),而將流重新轉化成對象的過程則是反序列化(Deserialization)。


下面是序列化對象信息:

public class Person implements Serializable
{
	private static final long	serialVersionUID	= 1L;
	private int		age;
	private String	name;

	public Person(String name, int age)
	{
		this.age = age;
		this.name = name;
	}

	public int getAge()
	{
		return age;
	}

	public void setAge(int age)
	{
		this.age = age;
	}

	public String getName()
	{
		return name;
	}

	public void setName(String name)
	{
		this.name = name;
	}

	@Override
	public String toString()
	{
		return "Person [ name = " + name + ", age = " + age + " ]";
	}
}

上面代碼有: private static final long serialVersionUID = 1L;
這個序列化ID的作用是用來決定是否可以反序列化。如果有兩個類,都實現了Serializable,且功能代碼完全一致,一個負責序列化,另一個負責反序列化,如果兩者的序列化ID不同,那麼不能相互序列化和反序列化。

通過write()方法把對象信息保存在文件;通過read方法把對象從文件提取出來,而不用通過構造方法生成。

public class Test
{

	public static void main(String[] args)
	{
		write();
		read();
	}

	private static void write()
	{
		Person student = new Person("shawn", 18);

		try
		{
			ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("seria.txt"));
			out.writeObject(student); //
			System.out.println("Object has been written.");
			out.close();
		} catch (FileNotFoundException e)
		{
			e.printStackTrace();
		} catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	private static void read()
	{
		try
		{
			ObjectInputStream in = new ObjectInputStream(new FileInputStream("seria.txt"));
			Person studentRead = (Person) in.readObject();
			System.out.println("Object is:");
			System.out.println(studentRead);
			in.close();
		} catch (FileNotFoundException e)
		{
			e.printStackTrace();
		} catch (IOException e)
		{
			e.printStackTrace();
		} catch (ClassNotFoundException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
默認情況下,是調用 ObjectOutputStream 的 defaultWriteObject 方法以及 ObjectInputStream 的 defaultReadObject 方法進行序列化和反序列化。但是,序列化文件不安全,所有程序都可以訪問。所以如果傳送的序列化對象數據比較敏感,則最好不用這個方式,而採用 writeObject 和 readObject 方法,進行用戶自定義的序列化和反序列化。自定義的 writeObject 和 readObject 方法可以允許用戶控制序列化的過程,比如可以在序列化的過程中動態改變序列化的數值。
發佈了32 篇原創文章 · 獲贊 4 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章