zoukankan      html  css  js  c++  java
  • Java 序列化代理模式

    package effectivejava.chapter12.item90;
    
    import java.io.*;
    
    /**
     * https://blog.csdn.net/Lirx_Tech/article/details/51303966
     * [疯狂Java]I/O:其它自定义序列化的方法(transient、writeReplace、readResolve、Externalizable)
     */
    
    /**
     * 1. 序列化Person时, 会调用调用writeReplace()生成一个PersonProxy对象, 然后对此对象进行序列化 (不是对Person类对象进行序列化,
     *      由序列化文件的内容可以得知, 可以查看序列化生成的文件, 文件中内容为如下图 (代码之后的图)
     *      ��sr1effectivejava.chapter12.item90.Person$PersonProxy_7R&Z��[IageLhobbytLjava/lang/String;Lnameq~xpt足球t张三
     * 2. 反序列化时, 会调用PersonProxy的readResolve()方法生成一个Person对象,
     *      最后返回此对象的拷贝 (通过PersonProxy类的readResolve方法和main方法中的输出可以看出)
     * 3. 因此, Person类的序列化工作完全交给PersonProxy类, 正如此模式的名称所表达的一样
     */
    public class Person implements Serializable {
        private final String name;
        private final String hobby;
        private final int age;
    
        public Person(String name, String hobby, int age) {
            System.out.println("Person(String name, String hobby, int age)");
    
            //约束条件
            if(age < 0 || age > 200) {
                throw new IllegalArgumentException("非法年龄");
            }
    
            this.name = name;
            this.hobby = hobby;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public String getHobby() {
            return hobby;
        }
    
        public int getAge() {
            return age;
        }
    
    
        private static class PersonProxy implements Serializable {
            private final String name;
            private final String hobby;
            private final int age;
    
            public PersonProxy(Person original) {
                System.out.println("PersonProxy(Person original)");
                this.name = original.getName();
                this.hobby = original.getHobby();
                this.age = original.getAge();
            }
    
            //反序列化时将序列化代理转变回为外围类的实例
            private Object readResolve() {
                System.out.println("PersonProxy.readResolve()");
                Person person = new Person(name, hobby, age);
                System.out.println("resolveObject: " + person);
                return person;
            }
        }
    
        private Object writeReplace() {
            System.out.println("Person.writeReplace()");
            return new PersonProxy(this); //readObject的时候是调用, PersonProxy的readResolve()
        }
    
        //此方法不会执行,为何?
        //实现writeReplace就不要实现writeObject了,因为writeReplace的返回值会被自动写入输出流中,
        // 就相当于自动这样调用:writeObject(writeReplace());
        private void writeObject(ObjectOutputStream out) {
            System.out.println("Person.writeObject()");
        }
    
        //防止攻击者伪造数据, 企图违反约束条件 (如: 违反年龄约束)
        private Object readObject(ObjectInputStream in) throws InvalidObjectException {
            System.out.println("Person.readObject()");
            throw new InvalidObjectException("Proxy required");
        }
    
        public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
            Person person = new Person("张三", "足球" ,25);
            ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("serial.ser"));
            out.writeObject(person);
            out.flush();
            out.close();
    
            Thread.sleep(1000);
    
            ObjectInputStream in = new ObjectInputStream(new FileInputStream("serial.ser"));
            Person deserPerson = (Person) in.readObject();
            System.out.println("main: " + person);
            in.close();
    
            if(person == deserPerson) {
                System.out.println("序列化前后是同一个对象");
            } else {
                //程序会走这一段, 反序列化会创建对象, 但是不会执行类的构造方法, 而是使用输入流构造对象
                System.out.println("序列化前后不是同一个对象, 哈哈哈");
            }
        }
    }
    
    /**
     * /Library/Java/JavaVirtualMachines/jdk-13.0.2.jdk/Contents/Home/bin/java -Dfile.encoding=UTF-8 -classpath /Users/didi/git/effective-java-3e-source-code/bin effectivejava.chapter12.item90.Person
     * Person(String name, String hobby, int age)
     * Person.writeReplace()
     * PersonProxy(Person original)
     * PersonProxy.readResolve()
     * Person(String name, String hobby, int age)
     * main: effectivejava.chapter12.item90.Person@3f99bd52
     * 序列化前后不是同一个对象, 哈哈哈
     *
     * Process finished with exit code 0
      */
    
  • 相关阅读:
    FineUI 单击菜单页面内容完全刷新,关闭Tab
    FineUI秘密花园(九) — 表单验证
    FineUI 选中多行获取行ID
    NPOI控制Excel格式
    ”那个人样子好怪。” “我也看到了,他好像一条狗。”
    投资条件
    setContentView+LayoutInflater=完美切换页面(两者一定要同时使用,setContentView提高切换页面速度必看)setContentView的秘密----续上
    设置PlaceHolder的颜色
    android 数据库
    行动,行动,再行动
  • 原文地址:https://www.cnblogs.com/cx2016/p/12926153.html
Copyright © 2011-2022 走看看