JAVA编程思想读书笔记(四)--对象的克隆

接上篇JAVA编程思想读书笔记(三)--RTTI

No1:

类的克隆

复制代码
public class MyObject implements Cloneable {
    int i;

    public MyObject(int i) {
        this.i = i;
    }

    @Override
    protected Object clone() {
        Object o = null;
        try {
            o = super.clone();
        } catch (CloneNotSupportedException e) {
            System.out.println("MyObject can't clone");
        }
        return o;
    }

    @Override
    public String toString() {
        return Integer.toString(i);
    }
}
复制代码
复制代码
public class LocalCopy {
    public static void main(String args[]) {
        check1();
        check2();
    }

    static MyObject g(MyObject v) {
        v.i++;
        return v;
    }

    static MyObject f(MyObject v) {
        v = (MyObject) v.clone();
        v.i++;
        return v;
    }

    private static void check1() {
        MyObject a = new MyObject(11);
        MyObject b = g(a);
        if (a == b) {
            System.out.println("a==b");
        } else {
            System.out.println("a!=b");
        }
        System.out.println("a=" + a);
        System.out.println("b=" + b);
    }

    private static void check2() {
        MyObject c = new MyObject(47);
        MyObject d = f(c);
        if (c == d) {
            System.out.println("c==d");
        } else {
            System.out.println("c!=d");
        }
        System.out.println("c=" + c);
        System.out.println("d=" + d);
    }
}
复制代码

输出结果

a==b
a=12
b=12
c!=d
c=47
d=48

若想克隆一个类,必须继承Cloneable,并且重写clone方法

g()演示的是按引用传递,它会修改外部对象,并返回对那个外部对象的一个引用。

f()是对自变量进行克隆,所以将其分离出来,并让原来的对象保持独立,甚至能返回指向这个新对象的一个句柄,而且不会对原来的对象产生任何副作用。

No2:

复制代码
public class Snake implements Cloneable {
    private Snake next;
    private char c;

    Snake(int i, char x) {
        c = x;
        if (--i > 0) {
            next = new Snake(i, (char) (x + 1));
        }
    }

    void increment() {
        c++;
        if (next != null) {
            next.increment();
        }
    }

    @Override
    public String toString() {
        String s = ":" + c;
        if (next != null) {
            s += next.toString();
        }
        return s;
    }

    @Override
    protected Object clone() {
        Object o = null;
        try {
            o = super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return o;
    }

    public static void main(String args[]) {
        Snake s = new Snake(5, 'a');
        System.out.println("s=" + s);
        Snake s2 = (Snake) s.clone();
        System.out.println("s2="+s2);
        s.increment();
        System.out.println("after s.increment:");
        System.out.println("s="+s);
        System.out.println("s2="+s2);
    }
}
复制代码

输出结果

s=:a:b:c:d:e
s2=:a:b:c:d:e
after s.increment:
s=:b:c:d:e:f
s2=:a:c:d:e:f

这个还需要再研究

No3:

深层复制

复制代码
public class CloneA implements Cloneable {
    private int i;

    public CloneA(int i) {
        this.i = i;
    }

    @Override
    protected Object clone() {
        Object o = null;
        try {
            o = super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return o;
    }
}
复制代码
复制代码
public class CloneB implements Cloneable {
    private int j;

    public CloneB(int j) {
        this.j = j;
    }

    @Override
    protected Object clone() {
        Object o = null;
        try {
            o = super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return o;
    }
}
复制代码
复制代码
public class CloneAB implements Cloneable {
    private CloneA cloneA;
    private CloneB cloneB;

    public CloneAB(int i, int j) {
        cloneA = new CloneA(i);
        cloneB = new CloneB(j);
    }

    @Override
    protected Object clone() {
        CloneAB o = null;
        try {
            o = (CloneAB) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        o.cloneA = (CloneA) o.cloneA.clone();
        o.cloneB = (CloneB) o.cloneB.clone();
        return o;
    }
}
复制代码
public class TextAB {
    public static void main(String args[]) {
        CloneAB ab = new CloneAB(11, 22);
        CloneAB r = (CloneAB) ab.clone();
    }
}

CloneAB由CloneA和CloneB两个对象合成,为了对其进行深层复制,必须同时克隆里面两个对象的句柄。

No4:

复制代码
public class A {}

public class B {}

public class C extends A implements Cloneable {
    @Override
    protected Object clone() {
        Object o = null;
        try {
            o = super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return o;
    }
}

public class D extends C {}
复制代码
复制代码
public class TextABCD {
    public static void main(String args[]) {
        A a = new A();
        B b = new B();
        C c = new C();
        D d = new D();

        c.clone();
        d.clone();
    }
}
复制代码

在添加克隆能力之前,编译器会阻止我们的克隆尝试。一旦在C类中添加了克隆能力,那么C及它的所有后代都可以克隆。

No5:

public class Ordinary {}
复制代码
public class WrongClone extends Ordinary {

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

public class IsCloneable extends Ordinary implements Cloneable {
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
复制代码
public class NoMore extends IsCloneable {
    @Override
    protected Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException();
    }
}
复制代码
final class ReallyNoMore extends NoMore {}

public class TryMore extends NoMore {
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

public class BackOn extends NoMore {
    private BackOn duplicate(BackOn b) {
        return new BackOn();
    }

    public Object clone() {
        return duplicate(this);
    }
}
复制代码
复制代码
public class CheckCloneable {
    static Ordinary tryToClone(Ordinary ord) {
        String id = ord.getClass().getName();
        Ordinary x = null;
        if (ord instanceof Cloneable) {
            try {
                System.out.println("Attempting " + id);
                x = (Ordinary) ((IsCloneable) ord).clone();
                System.out.println("Cloned " + id);
            } catch (CloneNotSupportedException e) {
                System.out.println("Could not clone " + id);
            }
        }
        return x;
    }

    public static void main(String args[]) {
        Ordinary[] ord = {new IsCloneable(),
                new WrongClone(),
                new NoMore(),
                new TryMore(),
                new BackOn(),
                new ReallyNoMore(),
        };
        Ordinary x = new Ordinary();
        for (int i = 0; i < ord.length; i++) {
            tryToClone(ord[i]);
        }
    }
}
复制代码

输出结果

复制代码
Attempting IsCloneable
Cloned IsCloneable
Attempting NoMore
Could not clone NoMore
Attempting TryMore
Could not clone TryMore
Attempting BackOn
Cloned BackOn
Attempting ReallyNoMore
Could not clone ReallyNoMore
复制代码

WrongClone没有继承Cloneable,所以不能克隆

IsCloneable是标准写法,可以克隆

NoMore直接抛异常,所以不能克隆

ReallyNoMore是final类,所以不能克隆

TryMore继承了NoMore直接抛异常,所以不能克隆

BackOn自己生成一个新对象,算是特殊的克隆

总之,如果希望一个类能够克隆

(1)实现Cloneable接口

(2)覆盖clone()

(3)在自己的clone()中调用super.clone()

(4)在自己的clone()中捕获违例

No6:

String的修改是生成了一个新的String对象,包括“+"的使用

posted @   嘉禾世兴  阅读(326)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
历史上的今天:
2016-08-23 保利威视点播集成
点击右上角即可分享
微信分享提示