1. 程式人生 > >單例模式的序列化與反序列化實現需要實現readResolve()方法

單例模式的序列化與反序列化實現需要實現readResolve()方法

package com.linruby.singleton;

import java.io.Serializable;

public class SingletonObject implements Serializable {
    private static final SingletonObject instance = new SingletonObject();
    private String name = "linruby12";
    private int age = 37;

    private SingletonObject() {

    }

    public static SingletonObject getInstance() {
        return instance;
    }

    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;
    }

    private Object readResolve() {
        return SingletonObject.getInstance();
    }

}
package com.linruby.singleton;

import java.io.*;

import static java.lang.System.out;
import static java.lang.System.setOut;

public class ClinetMain {

    public static void main(String[] args) {
        SingletonObject instance = SingletonObject.getInstance();
        FileOutputStream fout = null;
        ObjectOutputStream outObj = null;
        FileInputStream fin=null;
        ObjectInputStream inObj = null;
        try {
            fout = new FileOutputStream("d:/linruby12.obj");
            outObj = new ObjectOutputStream(fout);
            outObj.writeObject(instance);
            outObj.flush();

            fin = new FileInputStream("d:/linruby12.obj");
            inObj = new ObjectInputStream(fin);
            SingletonObject instance2 = (SingletonObject)inObj.readObject();

            System.out.println(instance);
            System.out.println(instance2);
            System.out.println(instance2.getName());
            System.out.println(instance2.getAge());

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fout != null) {
                try {
                    fout.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outObj != null) {
                try {
                    outObj.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            .....
        }
    }
}

結果:

[email protected]
[email protected]
linruby12
37

那麼這個readResolve()方法是從哪來的,為什麼加上之後就能返回同一例項了呢?
找到ObjectInputStream類的


/**
 * Reads and returns "ordinary" (i.e., not a String, Class,
 * ObjectStreamClass, array, or enum constant) object, or null if object's
 * class is unresolvable (in which case a ClassNotFoundException will be
 * associated with object's handle).  Sets passHandle to object's assigned
 * handle.
 */
private Object readOrdinaryObject(boolean unshared)
throws IOException
{
if (bin.readByte() != TC_OBJECT) {
throw new InternalError();
    }

    ObjectStreamClass desc = readClassDesc(false);
    desc.checkDeserialize();

    Class<?> cl = desc.forClass();
if (cl == String.class || cl == Class.class
|| cl == ObjectStreamClass.class) {
throw new InvalidClassException("invalid class descriptor");
    }

    Object obj;
try {
        obj = desc.isInstantiable() ? desc.newInstance() : null;
    } catch (Exception ex) {
throw (IOException) new InvalidClassException(
            desc.forClass().getName(),
"unable to create instance").initCause(ex);
    }

passHandle = handles.assign(unshared ? unsharedMarker : obj);
    ClassNotFoundException resolveEx = desc.getResolveException();
if (resolveEx != null) {
handles.markException(passHandle, resolveEx);
    }

if (desc.isExternalizable()) {
        readExternalData((Externalizable) obj, desc);
    } else {
        readSerialData(obj, desc);
    }

handles.finish(passHandle);

// 這個位置呼叫readResolve方法
if (obj != null &&
handles.lookupException(passHandle) == null &&
desc.hasReadResolveMethod())
    {
        Object rep = desc.invokeReadResolve(obj);
if (unshared && rep.getClass().isArray()) {
            rep = cloneArray(rep);
        }
if (rep != obj) {
handles.setObject(passHandle, obj = rep);
        }
    }

return obj;
}