woieha320r的博客

原型

用于复制已有对象,⚠️和单例相悖

· java的Object中有一个protected native Object clone()用于新建对象空间并复制成员值。在Java中做原型可通过实现标记型接口Cloneable 并重写clone(),但这只是浅克隆:只复制成员值,引用类型则只是复制了引用值。

· 在说单例时提到Java的反序列化可以保证新建对象,除非其声明了Object readResolve()。可以用这个机制达到深克隆的效果。

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;

import java.io.*;

abstract class Prototype implements Cloneable, Serializable {
    @Override
    public Prototype clone() throws CloneNotSupportedException {
        return (Prototype) super.clone();
    }

    public Prototype deepClone() throws IOException, ClassNotFoundException {
        try (
                ByteArrayOutputStream byteArrOutputStream = new ByteArrayOutputStream();
                ObjectOutputStream objOutputStream = new ObjectOutputStream(byteArrOutputStream)
        ) {
            objOutputStream.writeObject(this);
            try (
                    ByteArrayInputStream byteArrInputStream = new ByteArrayInputStream(byteArrOutputStream.toByteArray());
                    ObjectInputStream objInputStream = new ObjectInputStream(byteArrInputStream);
            ) {
                return (Prototype) objInputStream.readObject();
            }
        }
    }
}

@Getter
@Setter
class TestPrototype extends Prototype {

    @Getter
    @AllArgsConstructor
    static class Inner implements Serializable {
        private final int y;
    }

    private int x;
    private Inner inner;

    public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
        TestPrototype prototype1 = new TestPrototype();
        prototype1.setX(-1);
        prototype1.setInner(new Inner(-2));

        TestPrototype prototype2 = (TestPrototype) prototype1.clone();
        TestPrototype prototype3 = (TestPrototype) prototype1.deepClone();

        System.out.println("浅克隆——基本类型相等:" + (prototype1.getX() == prototype2.getX()));
        System.out.println("浅克隆——引用类型相等:" + (prototype1.getInner() == prototype2.getInner()));

        System.out.println("深克隆——基本类型相等:" + (prototype1.getX() == prototype3.getX()));
        System.out.println("深克隆——引用类型相等:" + (prototype1.getInner() == prototype3.getInner()));
    }
}