zoukankan      html  css  js  c++  java
  • 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/

  • 相关阅读:
    spring data jpa 分页查询(小结)
    java 工作日判断
    Map的merge方法(java8)
    java8 常用JVM 参数修改
    ubuntu docker client 安装
    scala io 读写文件
    Grafana 系统资源监测
    Java8Stream Collectors收集器
    EhCacheUtils 缓存 ehche (将文件临时保存在磁盘)
    springboot2.X 整合scala
  • 原文地址:https://www.cnblogs.com/sunfan1988/p/3649075.html
Copyright © 2011-2022 走看看