对象数组实例的深度副本,Java

对象数组实例的深度副本,Java,java,arrays,object,deep-copy,Java,Arrays,Object,Deep Copy,我在我的主配方recipeOne=新配方(“意大利香肠比萨饼”)中制作了一个对象 此对象是在此定义和构造的此对象数组的实例 public class Recipe implements Cloneable{ String Name; final int INGREDIENT_ARRAY_MAX = 10; Ingredient Recipe[] = new Ingredient[INGREDIENT_ARRAY_MAX]; public Recipe(String name){

我在我的主
配方recipeOne=新配方(“意大利香肠比萨饼”)中制作了一个对象

此对象是在此定义和构造的此对象数组的实例

public class Recipe implements Cloneable{

String Name;

final int INGREDIENT_ARRAY_MAX = 10;

Ingredient Recipe[] = new Ingredient[INGREDIENT_ARRAY_MAX];

public Recipe(String name){

    Name = name;

}
因此,我希望通过行
Recipe-pressippi=(Recipe)Recipe.clone()来创建此对象的深度副本它把我送到这里

public Object clone(){

    Recipe cloneRec = new Recipe(Name);

    return cloneRec;

}
我知道这是一个浅层复制,因为该方法只传递引用,所以如果我尝试更改recipeOne克隆的新对象的名称…它将更改它们的两个名称。很明显我不想这样,我对这件事很迷茫,有人能帮我吗

编辑:@Rohit Jain

我的配方类和配料类(配方数组持有的对象)都有toString方法和对配料的配方调用,以便以漂亮的小格式打印出来。当我在我的“recipeOne”对象(被称为意大利香肠比萨)上调用它时,我得到了“意大利香肠比萨:1.0磅的面团,8.0盎司的酱汁,10.0盎司的奶酪”


然后我继续制作对象Resippi,并将其设置为recipeOne的克隆,从这里开始一切都很好…然后我将Resippi的名称更改为“菠萝比萨饼”,打印出来的很好,但它不会打印recipeOne存储的3个配料对象,这是应该做的

正如您所发现的,实现
Cloneable
实际上并不克隆对象。您必须明智地实现
clone()
方法,如果您想要一个深度拷贝,这就是您应该实现的

现在,使用相同的
名称
属性创建一个新的
配方
对象就可以了。之后更改新对象的名称也很好,它不会更改第一个对象的名称,因为java
String
是不可变的

您可能想看看这个包,它为克隆对象提供了方便的代码

最后,关于“…仅传递引用…”,您应该阅读例如和线程


干杯,

连载它!下面以deepClone函数为例:

其他关于字符串不可变的回答当然是正确的,但是您试图用字符串示例描述的问题只是一个糟糕的例子;complexer对象(如配料数组)仍然是通过引用复制的

另外:更改数组的名称,使其与类名不匹配(=混淆):


将复制构造函数添加到recipe类,该类将创建recipe的新实例,并从原始recipe复制所有字段

Recipe.java

public class Recipe implements Cloneable {

    String name;

    final int INGREDIENT_ARRAY_MAX = 10;

    Ingredient[] ingredients = new Ingredient[INGREDIENT_ARRAY_MAX];

    public Recipe(String name) {
        this.name = name;
    }

    //Copy Constructor
    private Recipe(Recipe recipe){
        this.name = recipe.name;
        for(int x = 0; x < recipe.ingredients.length; x++){
            this.ingredients[x] = recipe.ingredients[x];
        }
    }

    public static Recipe newInstance(Recipe recipe){
        return new Recipe(recipe);
    }

    //Debug Method
    public static void printRecipe(Recipe recipe){
        System.out.println("Recipe: " + recipe.name);
        for(Ingredient i:recipe.ingredients){
          if(i != null && i.getName() != null){
              System.out.println("Ingredient: " + i.getName());           
          }
        }
    }

    //Test Method
    public static void main(String[] args) {
        Recipe recipe = new Recipe("Chicken Soup");
        recipe.ingredients[0] = new Ingredient("Chicken");
        recipe.ingredients[1] = new Ingredient("Broth");

        Recipe copy = new Recipe(recipe);
        copy.ingredients[2] = new Ingredient("Rice");
        copy.name = "Chicken Rice Soup";

        printRecipe(recipe);
        printRecipe(copy);
        System.out.println(recipe == copy);
        System.out.println(recipe.ingredients == copy.ingredients);
    }
}
public class Ingredient {

    private String name;

    public Ingredient(String name){
        this.name = name;
    }

    public String getName() {
        return name;
    }


    public void setName(String name) {
        this.name = name;
    }
}

看看这个答案:
newstring(name)
?这个答案已经很旧了,但我认为“this.components[x]=recipe.components[x];”不应该在深度副本中完成。您需要再次进一步执行每个元素的深度复制。
public class Ingredient {

    private String name;

    public Ingredient(String name){
        this.name = name;
    }

    public String getName() {
        return name;
    }


    public void setName(String name) {
        this.name = name;
    }
}