posts - 51, comments - 17, trackbacks - 0, articles - 9
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          java serializable

          Posted on 2007-03-09 20:13 chenweicai 閱讀(386) 評論(0)  編輯  收藏

          序列化概述

          簡單來說序列化就是一種用來處理對象流的機制,所謂對象流也就是將對象的內容進行流化,流的概念這里不用多說(就是I/O),我們可以對流化后的對象進行讀寫操作,也可將流化后的對象傳輸于網絡之間(注:要想將對象傳輸于網絡必須進行流化)!在對對象流進行讀寫操作時會引發一些問題,而序列化機制正是用來解決這些問題的!

          問題的引出:

          如上所述,讀寫對象會有什么問題呢?比如:我要將對象寫入一個磁盤文件而后再將其讀出來會有什么問題嗎?別急,其中一個最大的問題就是對象引用!舉個例子來說:假如我有兩個類,分別是A和B,B類中含有一個指向A類對象的引用,現在我們對兩個類進行實例化{ A a = new A(); B b = new B(); },這時在內存中實際上分配了兩個空間,一個存儲對象a,一個存儲對象b,接下來我們想將它們寫入到磁盤的一個文件中去,就在寫入文件時出現了問題!因為對象b包含對對象a的引用,所以系統會自動的將a的數據復制一份到b中,這樣的話當我們從文件中恢復對象時(也就是重新加載到內存中)時,內存分配了三個空間,而對象a同時在內存中存在兩份,想一想后果吧,如果我想修改對象a的數據的話,那不是還要搜索它的每一份拷貝來達到對象數據的一致性,這不是我們所希望的!

          以下序列化機制的解決方案:

          1.保存到磁盤的所有對象都獲得一個序列號(1, 2, 3等等)

          2.當要保存一個對象時,先檢查該對象是否被保存了。

          3.如果以前保存過,只需寫入"與已經保存的具有序列號x的對象相同"的標記,否則,保存該對象

          通過以上的步驟序列化機制解決了對象引用的問題!

          序列化的實現

          將需要被序列化的類實現Serializable接口,該接口沒有需要實現的方法,implements Serializable只是為了標注該對象是可被序列化的,然后使用一個輸出流(如:FileOutputStream)來構造一個ObjectOutputStream(對象流)對象,接著,使用ObjectOutputStream對象的writeObject(Object obj)方法就可以將參數為obj的對象寫出(即保存其狀態),要恢復的話則用輸入流。
          package serializable;

          import java.io.Serializable;

          public class Employee implements Serializable {

          ?private String name;
          ?
          ?private double salary;

          ?public Employee(String name, double salary) {
          ??super();
          ??// TODO Auto-generated constructor stub
          ??this.name = name;
          ??this.salary = salary;
          ?}
          ?
          ?public void raiseSalary(double byPercent){
          ??double temp = salary * byPercent / 100;
          ??salary += temp;
          ?}

          ?public String toString() {
          ??// TODO Auto-generated method stub
          ??return getClass().getName() +
          ???"[ Name = " + name + ", salary = " + salary +"]";
          ?}

          package serializable;

          public class Manager extends Employee {
          ?
          ?private Employee secretary;

          ?public Manager(String name, double salary) {
          ??super(name, salary);
          ??// TODO Auto-generated constructor stub
          ??secretary = null;
          ?}

          ?public Employee getSecretary() {
          ??return secretary;
          ?}

          ?public void setSecretary(Employee secretary) {
          ??this.secretary = secretary;
          ?}

          ?public String toString() {
          ??// TODO Auto-generated method stub
          ??return super.toString() + "[ secretary = " + secretary +"]";
          ?}
          ?
          }

          package serializable;

          import java.io.FileInputStream;
          import java.io.FileOutputStream;
          import java.io.ObjectInputStream;
          import java.io.ObjectOutputStream;

          public class Test {
          ?
          ?public static void main(String[] args){
          ??
          ??Employee employee = new Employee("LiLei", 1000);
          ??Manager manager1 = new Manager("Jim", 20000);
          ??manager1.setSecretary(employee);
          ??
          ??Employee[] staff = new Employee[2];
          ??staff[0] = employee;
          ??staff[1] = manager1;
          ??
          ??try{
          ???ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("employee.dat"));
          ???oos.writeObject(staff);
          ???oos.close();
          ???
          ???ObjectInputStream ois = new ObjectInputStream(new FileInputStream("employee.dat"));
          ???Employee[] newStaff = (Employee[])ois.readObject();
          ???ois.close();
          ???
          ???newStaff[0].raiseSalary(1000);
          ???
          ???for(int i=0; i<newStaff.length; i++)
          ????System.out.println(newStaff[i]);
          ???
          ??}catch(Exception e)
          ??{
          ???e.printStackTrace();
          ??}
          ?}
          }

          修改默認的序列化機制?

          在序列化的過程中,有些數據字段我們不想將其序列化,對于此類字段我們只需要在定義時給它加上transient關鍵字即可,對于transient字段序列化機制會跳過不會將其寫入文件,當然也不可被恢復。但有時我們想將某一字段序列化,但它在SDK中的定義卻是不可序列化的類型,這樣的話我們也必須把他標注為transient,可是不能寫入又怎么恢復呢?好在序列化機制為包含這種特殊問題的類提供了如下的方法定義:

          private?void readObject(ObjectInputStream in) throws

          IOException, ClassNotFoundException;

          private void writeObject(ObjectOutputStream out) throws

          IOException;

          (注:這些方法定義時必須是私有的,因為不需要你顯示調用,序列化機制會自動調用的)

          使用以上方法我們可以手動對那些你又想序列化又不可以被序列化的數據字段進行寫出和讀入操作。

          下面是一個典型的例子,java.awt.geom包中的Point2D.Double類就是不可序列化的,因為該類沒有實現Serializable接口,在我的例子中將把它當作LabeledPoint類中的一個數據字段,并演示如何將其序列化
          package transientTest;

          import java.awt.geom.Point2D;
          import java.io.IOException;
          import java.io.ObjectInputStream;
          import java.io.ObjectOutputStream;
          import java.io.Serializable;


          public class LabeledPoint implements Serializable {

          ?private String label;
          ?transient private Point2D.Double point;
          ?
          ?public LabeledPoint(String label, double x, double y) {
          ??super();
          ??// TODO Auto-generated constructor stub
          ??this.label = label;
          ??this.point = new Point2D.Double(x,y);
          ?}
          ?
          ?private void writeObject(ObjectOutputStream oos)throws IOException{
          ??
          ??oos.defaultWriteObject();
          ??oos.writeDouble(point.getX());
          ??oos.writeDouble(point.getY());
          ?}
          ?
          ?private void readObject(ObjectInputStream ois)throws IOException, ClassNotFoundException{
          ??
          ??ois.defaultReadObject();
          ??double x = ois.readDouble() + 1.0;
          ??double y = ois.readDouble() + 1.0;
          ??point = new Point2D.Double(x,y);
          ?}

          ?public String toString() {
          ??// TODO Auto-generated method stub
          ??return getClass().getName() + "[ Label = " + label + ", point.getX() = "
          ???+ point.getX() + ", point.getY() = " + point.getY() + "]";
          ?}
          }

          package transientTest;

          import java.io.FileInputStream;
          import java.io.FileOutputStream;
          import java.io.ObjectInputStream;
          import java.io.ObjectOutputStream;

          public class transientTest {

          ?public static void main(String[] args){
          ??LabeledPoint label = new LabeledPoint("Book", 5.0, 5.0);
          ??
          ??try{
          ???System.out.println("before:\n" + label);
          ???
          ???ObjectOutputStream oos = new ObjectOutputStream(
          ?????new FileOutputStream("c:\\label.txt"));
          ???oos.writeObject(label);
          ???oos.close();
          ???
          ???System.out.println("after:\n" + label);
          ???ObjectInputStream ois = new ObjectInputStream(
          ?????new FileInputStream("c:\\label.txt"));
          ???LabeledPoint label1 = (LabeledPoint)ois.readObject();
          ???ois.close();
          ???
          ???System.out.println("after add 1.0:\n" + label);
          ??}catch(Exception e)
          ??{
          ???e.printStackTrace();
          ??}
          ?}
          }


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 呼图壁县| 永年县| 达孜县| 深泽县| 文昌市| 广丰县| 鄂伦春自治旗| 静乐县| 广昌县| 始兴县| 西林县| 南川市| 镇巴县| 米泉市| 长顺县| 吴川市| 廉江市| 合肥市| 普洱| 防城港市| 大新县| 金湖县| 德格县| 淮南市| 前郭尔| 泸溪县| 葫芦岛市| 林周县| 通化市| 涟源市| 馆陶县| 怀远县| 陆川县| 中西区| 固阳县| 无为县| 泰宁县| 南澳县| 万盛区| 铜梁县| 余干县|