Java學習-序列化

參考資料: html

http://www.2cto.com/kf/201405/305380.html java

http://www.cnblogs.com/xdp-gacl/p/3777987.html 數據庫

 

  1. 序列化和反序列化的概念

  把對象轉換爲字節序列的過程稱爲對象的序列化 服務器

  把字節序列恢復爲對象的過程稱爲對象的反序列化 網絡

  對象的序列化主要有兩種用途: 併發

  1 把對象的字節序列永久地保存到硬盤上,一般存放在一個文件或者數據庫中; 工具

  2 在網絡上傳送對象的字節序列。 spa

  在不少應用中,須要對某些對象進行序列化,讓它們離開內存空間,入住物理硬盤,以便長期保存。好比最多見的是Web服務器中的Session對象,當有 10萬用戶併發訪問,就有可能出現10萬個Session對象,內存可能吃不消,因而Web容器就會把一些seesion先序列化到硬盤中,等要用了,再把保存在硬盤中的對象還原到內存中。 htm

  當兩個進程在進行遠程通訊時,彼此能夠發送各類類型的數據。不管是何種類型的數據,都會以二進制序列的形式在網絡上傳送。發送方須要把這個Java對象轉換爲字節序列,才能在網絡上傳送;接收方則須要把字節序列再恢復爲Java對象。 對象

  1. 什麼狀況下須要序列化 

  • 當你想把的內存中的對象保存到一個文件中或者數據庫中時候;
  • 當你想用套接字在網絡上傳送對象的時候;
  • 當你想經過RMI傳輸對象的時候;
  1. 如何實現序列化

將須要序列化的類實現Serializable或者Externalnalizable接口就能夠了,Serializable接口中沒有任何方法,能夠理解爲一個標記,即代表這個類能夠序列化。

 

  1. 序列化和反序列化例子

若是咱們想要序列化一個對象,首先要建立某些OutputStream(如FileOutputStream、ByteArrayOutputStream等),而後將這些OutputStream封裝在一個ObjectOutputStream中。這時候,只須要調用writeObject()方法就能夠將對象序列化,並將其發送給OutputStream(記住:對象的序列化是基於字節的,不能使用Reader和Writer等基於字符的層次結構)

而反序列的過程(即將一個序列還原成爲一個對象),須要將一個InputStream(如FileInputstream、ByteArrayInputStream等)封裝在ObjectInputStream內,而後調用readObject()便可。

/**

*

*/

package com.serializable;

 

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;

 

/**

* @author hugo

*

*/

public class Person implements Serializable {

private static final long serialVersionUID = 1L;

private String name="SheepMu";

private int age=24;

public static void main(String[] args)

{//如下代碼實現序列化

try

{

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("my.out"));

//輸出流保存的文件名爲 my.out ;ObjectOutputStream能把Object輸出成Byte流

Person Person=new Person();

oos.writeObject(Person);

oos.flush(); //緩衝流

oos.close(); //關閉流

} catch (FileNotFoundException e)

{

e.printStackTrace();

} catch (IOException e)

{

e.printStackTrace();

}

fan();//調用下面的 反序列化 代碼

}

public static void fan()//反序列的過程

{

ObjectInputStream oin = null;//局部變量必需要初始化

try

{

oin = new ObjectInputStream(new FileInputStream("my.out"));

} catch (FileNotFoundException e1)

{

e1.printStackTrace();

} catch (IOException e1)

{

e1.printStackTrace();

}

Person mts = null;

try {

mts = (Person ) oin.readObject();//由Object對象向下轉型爲Person對象

} catch (ClassNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

System.out.println("name="+mts.name);

System.out.println("age="+mts.age);

}

}

 

 

 

五、序列化ID

序列化 ID 在 Eclipse 下提供了兩種生成策略,一個是固定的 1L,一個是隨機生成一個不重複的 long 類型數據(其實是使用 JDK 工具生成),在這裏有一個建議,若是沒有特殊需求,就是用默認的 1L 就能夠,這樣能夠確保代碼一致時反序列化成功。這也多是形成序列化和反序列化失敗的緣由,由於不一樣的序列化id之間不能進行序列化和反序列化。

 

6.序列化前和序列化後的對象的關係

是 "=="仍是equal? or 是淺複製仍是深複製? 

答案:深複製,反序列化還原後的對象地址與原來的的地址不一樣

序列化先後對象的地址不一樣了,可是內容是同樣的,並且對象中包含的引用也相同。換句話說,經過序列化操做,咱們能夠實現對任何可Serializable對象的"深度複製(deep copy)"——這意味着咱們複製的是整個對象網,而不只僅是基本對象及其引用。對於同一流的對象,他們的地址是相同,說明他們是同一個對象,可是與其餘流的對象地址卻不相同。也就說,只要將對象序列化到單一流中,就能夠恢復出與咱們寫出時同樣的對象網,並且只要在同一流中,對象都是同一個。

 

7.靜態變量可否序列化

序列化會忽略靜態變量,即序列化不保存靜態變量的狀態。靜態成員屬於類級別的,因此不能序列化。即 序列化的是對象的狀態不是類的狀態。這裏的不能序列化的意思,是序列化信息中不包含這個靜態成員域。最上面添加了static後之因此仍是輸出24是由於該值是JVM加載該類時分配的值。注:transient後的變量也不能序列化

八、總結:

a)當一個父類實現序列化,子類自動實現序列化,不須要顯式實現Serializable接口;

b)當一個對象的實例變量引用其餘對象,序列化該對象時也把引用對象進行序列化;

c) static,transient後的變量不能被序列化;

相關文章
相關標籤/搜索