Java学习笔记

Clone() method in Java

2017-05-25  本文已影响24人  zac4j

原文:geeks4geeks

Java 中的 clone() 方法

对象 clone 是指创建对象的精确拷贝,它创建了一个当前对象新的实例并根据相应的值域的内容初始化所有的值域。

使用赋值操作符创建引用变量的拷贝

与 C++ 不同,没有运算符能创建对象的拷贝。如果使用赋值运算符它会创建当前对象引用的拷贝。这个可以见下面的例子:

// 简单的演示赋值运算符仅创建对象的引用的拷贝的例子
import java.io.*;

// 测试类
class Test {
  int x, y;
  Test() {
    x = 10;
    y = 20;
  }
}

// 驱动类
class Main{
  public static void main(String[] args) {
    Test ob1 = new Test();

    System.out.println(ob1.x + " " + ob1.y);

    // 创建一个新的引用变量 ob2 指向和 ob1 相同的内存地址
    Test ob2 = ob1;

    // 任何影响 ob2 的操作都会影响 ob1
    ob2.x = 100;

    System.out.println(ob1.x+" "+ob1.y);
    System.out.println(ob2.x+" "+ob2.y);
  }
}

输出:

10 20
100 20
100 20

使用 clone() 方法创建对象的拷贝

需要被创建拷贝的对象的类或父类必须有一个 publicclone() 方法。

protected Object clone() throws CloneNotSupportedException

clone() 方法的用法 —— 浅拷贝

// 简单的演示使用 clone() 方法实现浅拷贝的例子
import java.util.ArrayList;

class Test {
  int x, y;
}

// 包含 Test 对象的引用并实现了 clone 方法
class Test2 implements Cloneable {
  int a;
  int b;
  Test c = new Test();
  public Object clone() throws CloneNotSupportedException {
    return super.clone();
  }
}

// 驱动类
public class Main {
  public static void main(String args[]) throws CloneNotSupportedException {
    Test2 t1 = new Test2();
    t1.a = 10;
    t1.b = 20;
    t1.c.x = 30;
    t1.c.y = 40;

    // 创建 t1 的拷贝并赋值给 t2
    Test2 t2 = (Test2)t1.clone();

    // 改变 t2 中初始类型变量的值并不会影响 t1 的变量
    t2.a = 100;

    // 改变对象类型的值域会同时影响 t2 和 t1
    t2.c.x = 300;

    System.out.println(t1.a + " " + t1.b + " " + t1.c.x + " " + t1.c.y);
    System.out.println(t2.a + " " + t2.b + " " + t2.c.x + " " + t2.c.y);
  }
}

输出:

10 20 300 40
100 20 300 40

上例中,t1.clone 返回了 t1 对象的浅拷贝。为了获取对象的深拷贝,在获取拷贝之后还要在 clone() 方法中做一些修改。

深拷贝 vs 浅拷贝

clone() 方法的用法 —— 深拷贝

// 简单的演示使用 clone() 方法实现深拷贝的例子
import java.util.ArrayList;

class Test {
  int x, y;
}

// 包含 Test 对象的引用并实现了 clone() 方法
class Test2 implements Cloneable {
  int a, b;
  Test c = new Test();
  public Object clone() throws CloneNotSupportedException {
    // 将浅拷贝赋给引用变量 t
    Test2 t = (Test2)super.clone();
    t.c = new Test();

    // 为了创建深拷贝,为值域 c 创建新的对象并将其赋给浅拷贝
    return t;
  }
}

public class Main {
  public static void main(String args[]) throws CloneNotSupportedException {
    Test2 t1 = new Test2();
    t1.a = 10;
    t1.b = 20;
    t1.c.x = 30;
    t1.c.y = 40;

    Test2 t3 = (Test2)t1.clone();
    // 改变 t2 中初始类型的值域并不会影响 t1 的值域    
    t3.a = 100;

    // 改变 t2 中的对象值域并不会影响 t1 的对象值域(深拷贝)
    t3.c.x = 300;

    System.out.println(t1.a + " " + t1.b + " " + t1.c.x + " " + t1.c.y);
    System.out.println(t3.a + " " + t3.b + " " + t3.c.x + " " + t3.c.y);
  }
}

输出:

10 20 30 40
100 20 300 0

上例中,我们看到新创建的 Test 类的对象被赋给 Test2 类的 clone 方法的返回值。由于 t3 包含对象 t1 的深拷贝。因此任何对于对象 t3 中的对象值域 c 的改变都不会影响 t1。

clone 方法的优势:

上一篇下一篇

猜你喜欢

热点阅读