java流(二)

目录

1 ObjectOutputStream/ObjectInputStream的使用

2 序列化

3 具体序列化的过程

4 Externalizable的简易介绍

实现序列化的Person类

/**
 * 测试序列化所用的类
 */
class Person implements Serializable {
    private String username;
    private transient String password; //反序列化
    public Person(String username,String password) {
        this.username = username;
        this.password = password;
    }
    public String toString() {
        StringBuffer str = new StringBuffer();
        str.append("username=" + this.username+"
");
        str.append("password=" + this.password);
        return str.toString();
    }
}

注意 password字段使用了transient表示,该字段不实现序列化(即,读取这个类时这个字段的值恒定位null) 

 测试方法

public class SerializableTest2 {
    public static void main(String args[]) throws IOException, ClassNotFoundException {
        testObjectSeri();
        testObjectInSeri();
    }
    public static void testObjectSeri() throws IOException {
        Person person = new Person("测试", "java");
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.dat"));
        oos.writeObject("字符串");
        oos.writeObject(person);
        oos.flush();
        oos.close();
        System.out.println("入参:"+"
"+"字符串 "+"
"+person.toString());
    }
    public static void testObjectInSeri() throws IOException,
            ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.dat"));
        String str = (String) ois.readObject();
        System.out.println(str);
        Person person = (Person) ois.readObject();
        ois.close();
        System.out.println(person.toString());
    }
}

 执行结果

入参:
字符串 
username=测试
password=java
字符串
username=测试
password=null

注意读取数据时要按照传入顺序转换成对应的对象类型。

我们再来详细的看一下,序列化的过程

改造一下Person类

class Person implements Serializable {
    private String username;
    private transient String password; //反序列化
    public Person(String username,String password) {
        this.username = username;
        this.password = password;
    }
    public String toString() {
        StringBuffer str = new StringBuffer();
        str.append("username=" + this.username+"
");
        str.append("password=" + this.password);
        return str.toString();
    }
    
    private void writeObject(java.io.ObjectOutputStream out) throws IOException {
        System.out.println("writeObject invoked");
    }

    private void readObject(java.io.ObjectInputStream in) throws IOException,
            ClassNotFoundException {
        System.out.println("readObject invoked");
    }

    private Object writeReplace() throws ObjectStreamException {
        System.out.println("writeReplace invoked");
        return this;
    }
    private Object readResolve() throws ObjectStreamException {
        System.out.println("readResolve invoked");
        return this;
    }
}

继续使用上面的测试方法

执行结果

writeReplace invoked
writeObject invoked
入参:
字符串 
username=测试
password=java
字符串
readObject invoked
readResolve invoked
username=null
password=null

序列化与反序列化的内部执行按照以下顺序

    writeReplace --> writeObject 
    readObject -->  readResolve 

结论

当进行序列化的时候: 
首先JVM会先调用writeReplace方法,在这个阶段,我们可以进行张冠李戴,将需要进行序列化的对象换成我们指定的对象. (入口)
跟着JVM将调用writeObject方法,来将对象中的属性一个个进行序列化,我们可以在这个方法中控制住哪些属性需要序列化. 

当反序列化的时候: 
JVM会调用readObject方法,将我们刚刚在writeObject方法序列化好的属性,反序列化回来. 
然后在readResolve方法中,我们也可以指定JVM返回我们特定的对象(不是刚刚序列化回来的对象). 

另外 Externalizable 和是一个有实际方法需要实现的interface,包括writeExternal和readExternal: 

现在在person后面添加这2个方法

        public void readExternal(ObjectInput in) throws IOException,
                ClassNotFoundException {
            System.out.println("readExternal");
            
        }

        public void writeExternal(ObjectOutput out) throws IOException {
            System.out.println("writeExternal");
        }

执行结果

writeReplace invoked
writeExternal//-----覆盖之前的方法被执行
入参:
字符串 
username=测试
password=java
readExternal//-----覆盖之前的方法被执行
readResolve invoked
username=null
password=null

参考文章

http://www.cnblogs.com/xt0810/p/3642904.html

http://dovecat.iteye.com/blog/66044

http://blog.csdn.net/yakihappy/article/details/3979373

http://developer.51cto.com/art/200908/147650.htm

http://dusiguxia.blog.163.com/blog/static/55629316201162635435180/

原文地址:https://www.cnblogs.com/sunfan1988/p/3649075.html