gpt4 book ai didi

Java深度克隆问题

转载 作者:行者123 更新时间:2023-12-01 13:12:35 25 4
gpt4 key购买 nike

我正在学习Java中的对象克隆。我真的对浅克隆和深克隆感到困惑。下面是来自Core Java的示例代码

public class Employee implements Cloneable {
private String name;
private Date hireDay;

public Employee(String n,double s)
{
this.name=n;
hireDay=new Date();
}
public void setHireDay(int year,int month,int day)
{
Date newhireDay=new GregorianCalendar(year,month-1,day).getTime();
hireDay.setTime(newhireDay.getTime());
}
public Employee clone() throws CloneNotSupportedException
{
Employee cloned=(Employee) super.clone();
//clone mutable fields
//cloned.hireDay=(Date) hireDay.clone();
return cloned;
}
public String toString()
{
return "Employee[name=]"+ name+" salary= "+salary+" hireday.getTIme() "+hireDay+"]";
}
}
public class cloneTest {
public static void main(String[] args) {
try{
Employee original =new Employee("john");
Employee cloned=original.clone();
original.setHireDay(1993,2,22);
cloned.setHireDay(2000,11,22);
System.out.println("original="+original);
System.out.println("cloned= "+cloned);
}
catch(CloneNotSupportedException e){
e.printStackTrace();
}
}

}

在这种情况下,原始对象和克隆对象的输出是相同的。由于我没有克隆可变字段,因此对克隆对象所做的更改将影响原始对象。但是当我将方法 setHireDay 更改为:

public void setHireDay(int year,int month,int day)
{
hireDay=new GregorianCalendar(year,month-1,day).getTime();
}

我确实更改了克隆对象中的雇佣日字段的值,但它不会影响原始对象。我不知道为什么

最佳答案

在更改后的 setHireDay 方法中,“hireDay”变量指向另一个内存位置,而在第一个 setHireDay 方法中,内存位置未更改(但它引用的值已更改)。将像“hireDay”这样的对象变量视为指定内存地址(也称为指针)的原始长值会有所帮助。在此内存地址中存储实际的对象数据(如“hireDay”变量的时间值)。在 hireDay = new Date() 的情况下,内存地址发生变化,而在 hireDay.setTime(x) 的情况下,内存地址保持不变,但值所指内容已更改。

下面对此进行了演示(将其作为 Java 应用程序运行并将输出与源代码进行比较)以及如何制作深复制与浅复制的示例。

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Date;
import java.util.GregorianCalendar;

public class CloneTest implements Cloneable, Serializable {
private static final long serialVersionUID = 5971741470680723802L;

public static void main(String[] args) {

try {
CloneTest original = new CloneTest();

System.out.println();
System.out.println("### shallow clone");

CloneTest cloned=original.clone();
compare(original, cloned);
original.setHireDay(1993,2,22);
cloned.setHireDay(2000,11,22);
compare(original, cloned);

System.out.println();
System.out.println("### shallow clone - mutable hiredate");

cloned.hireDayMutable = true;
cloned.setHireDay(2002,11,22);
compare(original, cloned);

System.out.println();
System.out.println("### deep clone");

cloned = clone(original);
compare(original, cloned);
cloned.setHireDay(2004,11,22);
compare(original, cloned);

} catch(Exception e){
e.printStackTrace();
}
}

private Date hireDay;
public boolean hireDayMutable;

public CloneTest() {
super();
hireDay=new Date();
System.out.println("New instance");
}

public void setHireDay(int year, int month, int day) {

if (hireDayMutable) {
hireDay = new GregorianCalendar(year,month-1,day).getTime();
} else {
Date newhireDay = new GregorianCalendar(year,month-1,day).getTime();
hireDay.setTime(newhireDay.getTime());
}
}

public CloneTest clone() throws CloneNotSupportedException {

CloneTest cloned = (CloneTest)super.clone();
return cloned;
}

public String toString() {
return "CloneTest[hireday=" + hireDay + "]";
}

public static void compare(CloneTest original, CloneTest cloned) {

System.out.println();
System.out.println("The same object : " + (cloned == original));
System.out.println("The same hireDate: " + (cloned.hireDay == original.hireDay));
System.out.println("original = " + original);
System.out.println("cloned = " + cloned);
}

/**
* Clones an object by serializing and then unserializing it ("deep copy").
*/
@SuppressWarnings("hiding")
public static <T> T clone(T o) {
return clone(o, 512);
}

@SuppressWarnings({ "unchecked", "hiding" })
public static <T> T clone(T o, int bufSize) {
return (T) unserialize(serialize(o, bufSize));
}

public static byte[] serialize(Object o, int bufSize) {

ByteArrayOutputStream baos = new ByteArrayOutputStream(bufSize);
try {
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject((Serializable)o);
oos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
byte[] ba = baos.toByteArray();
// log.trace("Serialized size: {}", ba.length);
return ba;
}

public static Object unserialize(byte[] ba) {

Object o = null;
try {
ByteArrayInputStream bais = new ByteArrayInputStream(ba);
ObjectInputStream oin = new ObjectInputStream(bais);
o = oin.readObject();
} catch (Exception e) {
throw new RuntimeException(e);
}
return o;
}

}

关于Java深度克隆问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22740001/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com