java序列化

   关于序列化的文字已经是汗牛充栋了,这里我就讲一下我个人理解到的java序列化.

   什么是序列化?

     序列化是将对象变成一连串的字节的过程,反序列化就是把一连串字节变成对象的过程.

   什么情况下需要序列化

      希望把对象变成文件和数据库数据的时候

     在网络上以套接字的方式传输的时候

     通过RIM远程传输对象的时候

   首先,要理解为什么要用到序列化?如果我们有需要把对象永久的保存起来,就可以把java对象序列化文件,当需要的时候就可以反序列化成对象使用.

   java类实现序列化接口Serializable,这个类就可以实现序列化了

   代码实现序列化

  创建一个普通类

package org.fkjava.oa.base;

import java.io.Serializable;

public class Chen implements Serializable{

    private String name;
    private int age;
    public Chen(){
        System.out.println("无参");
    }
    
    public Chen(String name,int age){
        System.out.println("有参");
        this.name = name;
        this.age = age;
    }
    @Override
    public String toString(){
        
        return "[" + name + " " + age + "]";
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

序列化和反序列代码

package org.fkjava.oa.base;

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

public class Jia {

    public static void main(String[] args) throws Exception {
        File file = new File("a.out");
        ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(file));
        Chen chen = new Chen("chen",19);
        oo.writeObject(chen);
        System.out.println("--------");
        ObjectInputStream oi = new ObjectInputStream(new FileInputStream(file));
        Chen c = (Chen) oi.readObject();
        System.out.println(c);
    }
}

可以看出,反序列的时候,没有调用对象的无参构造函数

看看writeObject()代码到底做了什么

 ............
// remaining cases
            if (obj instanceof String) {
                writeString((String) obj, unshared);
            } else if (cl.isArray()) {
                writeArray(obj, desc, unshared);
            } else if (obj instanceof Enum) {
                writeEnum((Enum) obj, desc, unshared);
            } else if (obj instanceof Serializable) {
                writeOrdinaryObject(obj, desc, unshared);
            } else {
                if (extendedDebugInfo) {
                    throw new NotSerializableException(
                        cl.getName() + "\n" + debugInfoStack.toString());
                } else {
                    throw new NotSerializableException(cl.getName());
                }
            }
..........

可以看出只要是string,数组,枚举和实现了Serializable

 

如果希望某个属性不被序列化的,需要怎么做呢.

使用transient

package org.fkjava.oa.base;

import java.io.Serializable;

public class Chen implements Serializable{

    private String name;
    private transient int age;
    public Chen(){
        System.out.println("无参");
    }
    
    public Chen(String name,int age){
        System.out.println("有参");
        this.name = name;
        this.age = age;
    }
    @Override
    public String toString(){
        
        return "[" + name + " " + age + "]";
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

如果不去掉transient,但是又想把对象的属性序列化到文件,怎么做呢.

private void writeObject(ObjectOutputStream oo) throws IOException{
        System.out.println("write");
        oo.defaultWriteObject();
        oo.writeInt(age);
    }
    private void readObject(ObjectInputStream oi) throws IOException, ClassNotFoundException{
        System.out.println("read");
        oi.defaultReadObject();
        int age = oi.readInt();
    }

当序列化和反序列化对象的时候,默认是调用对象的writeObject和readObject方法,但是他们都是private,怎么调用你,明显是使用了反射.

如果实现序列化单例,当时反序列化出来的对象就不是单例了,这时候怎么办

    private Object readResolve(){
        System.out.println("redResolve");
        return Chen.getInstance();
    }

ObjectInputStream会提供一个方法readResolve,只要实现了这个方法,用户在设置返回的对象,这个对象就作为readObject返回的对象,如果没有实现,系统默认选取

writeObject的对象.

posted @ 2015-08-10 21:29  如果可以在重来  阅读(176)  评论(0编辑  收藏  举报