📜  Java中的可克隆接口

📅  最后修改于: 2022-05-13 01:54:50.946000             🧑  作者: Mango

Java中的可克隆接口

Java.lang.Cloneable接口是一个标记接口。它是在 JDK 1.0 中引入的。 Object 类中有一个方法 clone()。 Cloneable接口由类实现,使 Object.clone() 方法有效,从而进行字段对字段的复制。此接口允许实现类克隆其对象,而不是使用new运算符。

宣言

public interface Cloneable

示例 1:下面的程序解释了如果您尝试克隆一个没有实现 Cloneable 接口的对象,它会是CloneNotSupportedException ,您可能想要处理它。

Java
// Java program to Demonstrate the
// application of Cloneable interface
  
import java.io.*;
import java.util.*;
  
class Student {
  
    // attributes of Student class
    String name = null;
    int id = 0;
  
    // default constructor
    Student() {}
  
    // parameterized constructor
    Student(String name, int id)
    {
        this.name = name;
        this.id = id;
    }
    
    public static void main(String[] args)
    {
        // create an instance of Student
        Student s1 = new Student("Ashish", 121);
  
        // Try to clone s1 and assign
        // the new object to s2
        Student s2 = s1.clone();
    }
}


Java
// Java program to illustrate Cloneable interface
import java.lang.Cloneable;
  
// By implementing Cloneable interface
// we make sure that instances of class A
// can be cloned.
class A implements Cloneable {
    int i;
    String s;
  
    // A class constructor
    public A(int i, String s)
    {
        this.i = i;
        this.s = s;
    }
  
    // Overriding clone() method
    // by simply calling Object class
    // clone() method.
    @Override
    protected Object clone()
        throws CloneNotSupportedException
    {
        return super.clone();
    }
}
  
public class Test {
    public static void main(String[] args)
        throws CloneNotSupportedException
    {
        A a = new A(20, "GeeksForGeeks");
  
        // cloning 'a' and holding
        // new cloned object reference in b
  
        // down-casting as clone() return type is Object
        A b = (A)a.clone();
  
        System.out.println(b.i);
        System.out.println(b.s);
    }
}


Java
// A Java program to demonstrate deep copy
// using clone()
import java.util.ArrayList;
  
// An object reference of this class is
// contained by Test2
class Test {
    int x, y;
}
  
// Contains a reference of Test and implements
// clone with deep copy.
class Test2 implements Cloneable {
    int a, b;
  
    Test c = new Test();
  
    public Object clone() throws CloneNotSupportedException
    {
        // Assign the shallow copy to new reference variable
        // t
        Test2 t = (Test2)super.clone();
  
        t.c = new Test();
  
        // Create a new object for the field c
        // and assign it to shallow copy obtained,
        // to make it a deep copy
        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();
        t3.a = 100;
  
        // Change in primitive type of t2 will not
        // be reflected in t1 field
        t3.c.x = 300;
  
        // Change in object type field of t2 will not
        // be reflected in t1(deep copy)
        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);
    }
}


输出:

prog.java:28: error: incompatible types: Object cannot be converted to Student
        Student s2 = s1.clone();
                             ^
1 error

示例 2:下面的代码解释了正确使用 Cloneable 接口以使 Object.clone() 方法合法。实现此接口的类应覆盖 Object.clone() 方法(受保护),以便可以调用它。

Java

// Java program to illustrate Cloneable interface
import java.lang.Cloneable;
  
// By implementing Cloneable interface
// we make sure that instances of class A
// can be cloned.
class A implements Cloneable {
    int i;
    String s;
  
    // A class constructor
    public A(int i, String s)
    {
        this.i = i;
        this.s = s;
    }
  
    // Overriding clone() method
    // by simply calling Object class
    // clone() method.
    @Override
    protected Object clone()
        throws CloneNotSupportedException
    {
        return super.clone();
    }
}
  
public class Test {
    public static void main(String[] args)
        throws CloneNotSupportedException
    {
        A a = new A(20, "GeeksForGeeks");
  
        // cloning 'a' and holding
        // new cloned object reference in b
  
        // down-casting as clone() return type is Object
        A b = (A)a.clone();
  
        System.out.println(b.i);
        System.out.println(b.s);
    }
}
输出
20
GeeksForGeeks

使用 clone() 方法进行深度复制

深度对象克隆就像通过将字段从原始对象复制到克隆对象来创建原始对象的精确副本。为复制原始对象内容的克隆对象分配单独的内存。 clone() 方法可以根据它的实现创建原始对象的浅拷贝和深拷贝。深拷贝创建一个与原始对象内容相同的新内存。这就是为什么当我们在克隆后更改原始对象的内容时,更改不会反映在克隆对象中。有深拷贝、浅拷贝和懒惰拷贝等类型。下面的代码解释了使用 clone() 方法的深层复制。

Java

// A Java program to demonstrate deep copy
// using clone()
import java.util.ArrayList;
  
// An object reference of this class is
// contained by Test2
class Test {
    int x, y;
}
  
// Contains a reference of Test and implements
// clone with deep copy.
class Test2 implements Cloneable {
    int a, b;
  
    Test c = new Test();
  
    public Object clone() throws CloneNotSupportedException
    {
        // Assign the shallow copy to new reference variable
        // t
        Test2 t = (Test2)super.clone();
  
        t.c = new Test();
  
        // Create a new object for the field c
        // and assign it to shallow copy obtained,
        // to make it a deep copy
        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();
        t3.a = 100;
  
        // Change in primitive type of t2 will not
        // be reflected in t1 field
        t3.c.x = 300;
  
        // Change in object type field of t2 will not
        // be reflected in t1(deep copy)
        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

注意:此接口不包含 clone 方法。因此,不能仅仅凭借对象实现了这个接口就克隆一个对象。即使以反射方式调用 clone 方法,也不能保证它会成功。

参考: Java : Java