我正在研究clone()
课程的Object
方法。我试过以下例子。
public class Orange {
private Double price;
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
}
public class Fruit implements Cloneable {
private String colour;
private String fruitCode;
private Orange orange;
public String getColour() {
return colour;
}
public void setColour(String colour) {
this.colour = colour;
}
public String getFruitCode() {
return fruitCode;
}
public void setFruitCode(String fruitCode) {
this.fruitCode = fruitCode;
}
public Orange getOrange() {
return orange;
}
public void setOrange(Orange orange) {
this.orange = orange;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public boolean equals(Object obj) {
Fruit other = (Fruit)obj;
return new EqualsBuilder().append(this.getFruitCode(), other.getFruitCode()).append(this.colour, other.colour).isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder().append(this.getFruitCode()).append(this.colour).toHashCode();
}
}
public class CloneTest {
public static void main(String[] args) {
Fruit fruit = new Fruit();
try {
fruit.setOrange(new Orange());
fruit.getOrange().setPrice(12.45);
fruit.setFruitCode("X1");
Fruit clonedFruit = (Fruit) fruit.clone();
fruit.setFruitCode("X2");
fruit.getOrange().setPrice(15.5);
System.out.println("fruit's orange price is : "+fruit.getOrange().getPrice());
System.out.println("clonedFruit's orange price is : "+clonedFruit.getOrange().getPrice());
System.out.println("fruit's code is : "+fruit.getFruitCode());
System.out.println("fruit's code is : "+clonedFruit.getFruitCode());
} catch (CloneNotSupportedException ex) {
Logger.getLogger(CloneTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
**out put is**
fruit's orange price is : 15.5
clonedFruit's orange price is : 15.5
fruit's code is : X2
fruit's code is : X1
请注意,我在克隆对象后更改了orange
对象的价格字段和水果的fruitCode
字段。但我已经通知了一个问题,即我为橙色对象的价格字段所做的更改已经受到了对象的影响,这些对象是原始对象和克隆对象。 但果实的水果代码领域并没有发生这种情况
而且当我把下面一行显示为打印为真时。
System.out.println(fruit.getOrange()== clonedFruit.getOrange());
我有点困惑,觉得clonedFruit和水果参考都指向同一个橙色物体。当我搜索在线文章时,我注意到了可变对象的克隆问题。 但对我来说不够明确。 任何人都可以清楚地向我解释它是如何发生的,我该怎么做才能阻止这个
答案 0 :(得分:3)
可悲的是,默认的object.clone()方法并不总是产生一个实际的克隆。克隆基本变量时,复制一个值,但是,如果克隆一个对象,它会将地址复制到该对象而不是它的值。
这就是为什么你通常应该为你的类定义你自己的克隆方法(可能有一些语法错误,但逻辑就在那里。
@Override
protected Object clone() throws CloneNotSupportedException {
Orange orange = new Orange();
//copy every basic variable
orange.setPrice(price);
//clone any Objects that have clone() method defined;
orange.setImage(this.Image.clone()); //just an example because you don't have 1 in your code
// for any objects that do not have clone() defined you have to copy each field manually
GeneticStructure gn = new GeneticStructure();
gn.setGeneticCode( this.geneticStructure.getGeneticCode());
gn.setName( this.geneticStructure.getGeneticStructire());
orange.setGeneticStructure( gn )
return orange;
}
答案 1 :(得分:0)
默认情况下, clone()方法始终返回要克隆的对象的浅层副本。这意味着它将复制基本类型变量的值并复制引用类型变量的引用。
让我们举个例如你的Fruit课程:
注意:您的Fruit类不一定需要实现Cloneable接口,因为它已经由Object实现,它始终是任何Java类的超类。
public class Fruit implements Cloneable {
private String colour;
private String fruitCode;
private Orange orange;
// Remaining methods
}
现在,当您创建Friut类的对象并将橙色引用变量初始化为:
Fruit fruit = new Fruit();
fruit.setOrange(new Orange());
然后,创建一个新的 Orang e类对象,并将其引用分配给 Fruit 对象的变量 orange 。
但是,当你打电话时:
Fruit clonedFruit = (Fruit)fruit.clone();
然后,内部不会创建新的橙色对象,而是将以上创建的橙色对象引用提供给引用变量指向它。这就是为什么你得到 true 的原因:
System.out.println(fruit.getOrange()== clonedFruit.getOrange()); // true
但是,肯定会创建一个新的Fruit对象。 所以,当你致电:
fruit.getOrange().setPrice(12.5);
然后
fruit.getOrange().setPrice(15.5);
后者将基本上覆盖先前的值,并且对象即fruit和clonedFruit都可以看到此修改,因为两者都包含对同一Orange对象的引用。 但是,当你打电话时:
fruit.setFruitCode("X1");
Fruit clonedFruit = (Fruit) fruit.clone();
然后,创建一个新的Fruit类对象,此处的 clonedFruit 对象仅包含fruitCode值为“X1”, 以后你打电话的时候:
fruit.setFruitCode("X2");
然后只会影响 fruit 对象的 fruitCode 值,该值现在将更改为“X2”。但这不会影响clonedFruit的 fruitCode 值,因为 fruit 和 clonedFruit 是两个不同的对象