如果一个待拷贝的对象域中含有引用类型,使用默认的clone方法,必然不能将引用类型的域值重新“生成”一个,原因在于,引用类型存放的是某个堆内对象的地址。JAVA默认的clone方法是浅拷贝,也就是说,新生成的那个对象的引用类型只是把待拷贝对象的地址又拷贝了一遍,于是乎,clone前和clone后的对象关于引用域值的属性必然指向了同一块内存(对象)。这种结果并不是我们真正想要的拷贝结果,因为如果修改clone前的域值,clone后对象的域值也会相应变化,就不一是一般意义上的“克隆”了。要想改变这个情况,必须要程序员对想要拷贝对象中重新声明clone方法,如下例红色部分。
import java.util.*;
public class CloneTest
{
public static void main(String[] args)
{
try
{
Employee original = new Employee("John Q. Public", 50000);
original.setHireDay(2000, 1, 1);
Employee copy = original.clone();
copy.raiseSalary(10);
copy.setHireDay(2002, 12, 31);
System.out.println("original=" + original);
System.out.println("copy=" + copy);
}
catch (CloneNotSupportedException e)
{
e.printStackTrace();
}
}
}
class Employee implements Cloneable
{
public Employee(String n, double s)
{
name = n;
salary = s;
}
[b] public Employee clone() throws CloneNotSupportedException
{
// call Object.clone()
Employee cloned = (Employee)super.clone();
// clone mutable fields
[color=red] cloned.hireDay = (Date)hireDay.clone();[/color]
return cloned;
}[/b]
/**
Set the hire day to a given date
@param year the year of the hire day
@param month the month of the hire day
@param day the day of the hire day
*/
public void setHireDay(int year, int month, int day)
{
hireDay = new GregorianCalendar(year, month - 1, day).getTime();
}
public void raiseSalary(double byPercent)
{
double raise = salary * byPercent / 100;
salary += raise;
}
public String toString()
{
return "Employee[name=" + name
+ ",salary=" + salary
+ ",hireDay=" + hireDay
+ "]";
}
private String name;
private double salary;
private Date hireDay;
}
如此这般,clone方法便不是浅拷贝了,是真正意义上的“克隆”了。
分享到:
相关推荐
Java Clone 深拷贝与浅拷贝的两种实现方法 Java Clone 是 Java 语言中的一种复制对象的机制,它可以将一个对象的所有属性和状态复制到另一个对象中,实现对象的深拷贝和浅拷贝。下面我们将讨论 Java 中的深拷贝和浅...
- 实现`Cloneable`接口并重写`clone()`方法需要注意,`clone()`默认执行的是浅拷贝,需要在子类中显式调用`super.clone()`并处理引用类型的字段。 - 序列化和反序列化可能涉及性能开销,不适合大量或频繁的复制...
总之,了解浅拷贝和深拷贝的区别及其在C#中的实现方法对于编写高效且无意外副作用的代码至关重要。无论是通过`MemberwiseClone`、反射还是序列化/反序列化,选择正确的拷贝策略取决于你的具体需求和性能考虑。
### C#中的浅拷贝与深拷贝 在C#编程语言中,对象的复制是一项基本而重要的操作。根据复制的方式不同,可以分为浅拷贝(Shallow Copy)和深拷贝(Deep Copy)。这两种复制方式各有其特点和适用场景。 #### 值类型...
在这个例子中,`Clone()`方法创建了一个新的`MyClass`实例,并且通过创建新的字符串对象实现了深拷贝。 `CloneDemo`可能是一个示例项目,它包含了关于如何在C#中实现浅拷贝和深拷贝的代码。通过分析和运行这个项目...
java设计模式【之】原型模式、深拷贝与浅拷贝【源码】【场景:克隆羊】 * 原型模式(Prototype) * 实现方式: * 需要被克隆的 class类, 重写Object中的clone()方法,并实现Cloneable接口(否则报错 ...
在这个例子中,`ClassB` 的 `Clone()` 方法通过调用 `Member.Clone()` 来为 `Member` 字段创建一个深拷贝。 ### 应用场景 选择使用深拷贝还是浅拷贝取决于具体需求。如果对象的字段只包含值类型或者不需要独立于...
`TestString`类中的`main`方法展示了浅拷贝、默认`clone()`方法实现的深拷贝以及序列化实现的深拷贝的用法。`qianCopyTest()`展示了浅拷贝的效果,其中对于包含可变对象的`Person`实例,修改副本会影响原始对象。`...
目录一、深拷贝与浅拷贝解析浅拷贝深拷贝二、数组拷贝的方式1.for循环来拷贝2.System.arraycopy( )拷贝3.Arrays.copyOf( )拷贝4.clone( )拷贝5.解释三、四种拷贝方式效率比较1. System.arraycopy( )2.Arrays.copyOf...
4. **浅拷贝与深拷贝示例**: 在给出的例子中,我们有两个测试类`Test2`和`Test3`,分别演示了浅拷贝和深拷贝的效果。 - 在`Test2`中,通过简单赋值创建了一个新的`Test`对象`t2`,这是浅拷贝。当修改`t2`的属性时...
总之,理解和掌握浅拷贝与深拷贝的概念及其实现方法,对于优化代码性能、防止意外数据修改以及提升程序的健壮性至关重要。在开发过程中,应根据实际情况选择合适的方式进行对象复制,以满足业务需求。
在C#中,实现深拷贝有多种方法,包括手动实现Clone方法、使用序列化和反序列化,以及使用第三方库如AutoMapper。 以下是通过序列化和反序列化实现深拷贝的例子: ```csharp using System.IO; using System.Runtime...
在Java中,通过实现`Cloneable`接口并覆盖`Object`类的`clone()`方法,可以实现浅拷贝。以下代码展示了浅拷贝的例子: ```java public class ShallowCopy { public static void main(String[] args) { Professor0...
实现深拷贝通常需要手动编写代码来复制每个字段,或者实现`ICloneable`接口并重写`Clone()`方法。 以下是一个简单的例子来说明深拷贝和浅拷贝的区别: ```csharp public class Person { public int Age { get; ...
Java的`clone()`方法默认执行的是浅拷贝,因为它只复制对象本身,不处理对象内引用的其他对象。为了实现深拷贝,我们需要重写`clone()`方法,并在其中处理引用类型的数据,确保每个引用都被复制到新的内存区域。此外...
1、定义 原型模式(Prototype)是通过复制一个已经存在的实例来返回新的实例,而不是新建实例,被复制的实例是我们所称的... (1)利用Java中的clone方法深拷贝与浅拷贝 浅拷贝: public class Professor { pri
在JavaScript编程中,深拷贝和浅拷贝是两种常见的数据复制方法。深拷贝创建了一个新对象,这个新对象复制了原始对象的所有属性,并且这些属性的值都是原始对象属性值的副本,包括嵌套的对象和数组。这意味着对深拷贝...
1. **浅拷贝与深拷贝**: - 浅拷贝:当一个对象被复制时,它的所有字段都被复制,但对引用类型的字段仅复制引用,而不是复制引用的对象。这意味着原始对象和副本指向内存中的同一个对象。 - 深拷贝:如果需要完全...
clone()方法是Object类中的一个方法,它可以用来实现对象的浅拷贝。但是,如果我们想要实现深拷贝,那么需要将所有涉及到的类实现声明式接口Cloneable,并覆盖Object类中的clone()方法,并设置作用域为public。这是...
### Java中的`clone`方法详解:浅拷贝与深拷贝 #### 一、引言 在Java中,`clone`方法提供了一种快速复制对象的方式。它属于`Object`类的一部分,但需要显式地在子类中声明并实现`Cloneable`接口才能正常使用。本文...