显示浅克隆和深克隆的Java程序
clone 方法的默认版本创建对象的浅拷贝。在面向对象的Java中,对象复制是创建现有对象的副本,因此复制的对象可以是复制对象的精确副本的类似副本。有两种方法可以复制对象,如下所示:
在 C/C++ 中有
复制方法
现在,复制可以分为以下三种类型:
- 浅拷贝
- 深拷贝
- 克隆
通常,深度复制和克隆被称为相同的深度克隆,因为它们之间的区别是一条细线,重点放在一条细线上,以便于使用 clone() 方法手动复制对象。
1. 浅拷贝/克隆
- 使用 clone() 方法时的默认实现是创建对象的浅拷贝。这意味着它会创建一个新实例并将对象的所有字段复制到该新实例,其中两者都引用堆内存中的相同内存。
- 对象类的clone()方法支持对象的浅拷贝。如果对象在浅拷贝中包含原始以及非原始或引用类型变量,则克隆对象还引用原始对象所引用的同一对象,因为仅复制对象引用而不是引用对象本身。简单来说,这里创建了一个对象,而堆栈内存中有两个引用。
- 它将它作为对象类型返回,我们需要将它显式转换回我们的原始对象。这是对象的浅拷贝。
插图:浅拷贝对象“t2”
class GFG
{
int i,j;
}
main(String[] args)
{
// Copying
GFG object1 = new GFG() ;
object.i = 5;
object.j = 6;
GFG object2 = object1 ; // shallow copying object
}
示例 1
Java
// Java Program to show shallow cloning
// Importing java input/output classes
import java.io.*;
// Class
class GFG {
// Main driver method
public static void main(String[] args)
{
// t1 and t2 objects are used to
// illustrate shallow copy
// t1 is first object created in heap memory
GFG t1 = new GFG();
// Creating only one object(t1) and
// both objects (t1,t2) are pointing to only one
// object
GFG t2 = t1;
// Display message
// return true if reference is same that is shallow copy
// false if different
// Should be returning - true
System.out.print(
"Output: False if Deepcopy & True if shallow : ");
System.out.println(t1 == t2);
}
}
Java
// Java Program to show Deep Cloning
// Importing java input/output libraries
import java.io.*;
// Class
public class GFG implements Cloneable {
// Defining a method as clone method is protected
// Defining within the class called cloneable interface
public Object clone() throws CloneNotSupportedException
{
return (GFG)super.clone();
}
// Main driver method
public static void main(String[] args) throws CloneNotSupportedException
{
// Creating first object of GFG class
GFG t1 = new GFG();
// Using clone() method to create duplicate object
// of t1 reference variable
// else for every object manually object needs
// to be copied in deep copying
// clone() ease this manual effort
GFG t2 = (GFG)t1.clone();
// Comparing two objects just after deep copying
// Returning true for shallow(by default) copying
// Returning false for deep copying
System.out.println(t1 == t2);
}
}
输出
Output: False if Deepcopy & True if shallow : true
输出说明:
- 如上所示,有两个参考变量 t1、t2。每当创建 GFG 类的对象时,t1(引用变量)就指向一个对象。
- 之后,将t1引用变量赋值给堆内存中指向同一个对象的同一个类的新引用变量t2。 t1 和 t2 引用变量都只指向一个对象。
- 它不会创建新的重复对象。以上两条语句证明t1和t2引用变量都只指向一个对象。
2. 深度复制/克隆是在堆内存中准确创建独立的重复对象并手动分配应该复制值的第二个对象的值的过程称为深度克隆。
- 每当需要不使用默认实现的自我复制时,都称为深度复制,其中需要的对象是根据需要实现的。因此,对于深拷贝,需要保证所有的成员类也都实现了Cloneable接口,因为重写了对象类的clone()方法。
GFG object1 = new GFG() ; || Creating object of GFG class
object.i = 5;
object.j = 6;
GFG object2 = new GFG; || Creating another object class
object2.i = object1.i ; || Deep copying
object2.j = object1.j ; || Deep copying
Note: In can not directly call clone() method using object.clone() as clone method in Object class of java is protected. So override the function by making access modifier as public in return super.clone() from the class created to override
示例 2
Java
// Java Program to show Deep Cloning
// Importing java input/output libraries
import java.io.*;
// Class
public class GFG implements Cloneable {
// Defining a method as clone method is protected
// Defining within the class called cloneable interface
public Object clone() throws CloneNotSupportedException
{
return (GFG)super.clone();
}
// Main driver method
public static void main(String[] args) throws CloneNotSupportedException
{
// Creating first object of GFG class
GFG t1 = new GFG();
// Using clone() method to create duplicate object
// of t1 reference variable
// else for every object manually object needs
// to be copied in deep copying
// clone() ease this manual effort
GFG t2 = (GFG)t1.clone();
// Comparing two objects just after deep copying
// Returning true for shallow(by default) copying
// Returning false for deep copying
System.out.println(t1 == t2);
}
}
输出
false
输出说明:
- 这里有两个参考变量t1、t2。创建GFG类的对象时,t1(引用变量)指向一个对象。
- 之后,将 t1 赋值为引用变量,并调用clone()方法到同一类的新引用变量 t2 中。 t1 和 t2 引用变量都指向不同的对象。这里 t2 创建了一个新的重复对象,t1 也创建了。
- 以上两条语句证明,如果t1指向O1对象而不是t2指向O2对象,则t1和t2引用变量都是点差对象。