Глубокая копия экземпляра массива объектов, Java


У меня есть объект, сделанный в моей главной Recipe recipeOne = new Recipe("Pepperoni Pizza");

Этот объект является экземпляром этого массива объектов, определенного и построенного здесь!

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 ressippi = (Recipe) recipe.clone();, и он посылает меня сюда!

public Object clone(){

    Recipe cloneRec = new Recipe(Name);

    return cloneRec;

}

Я знаю, что в настоящее время это неглубокая копия, потому что метод передает только ссылки, поэтому, если бы я попытался изменить имя моего нового объекта, который был клоном recipeOne...it изменил бы оба их имени. Очевидно, что я не хочу что, я совсем запутался в этом, может кто-нибудь помочь?

EDIT:@Rohit Джайн

Как мой класс рецептов, так и мой класс ингредиентов (объекты, которые содержит массив рецептов) имеют методы toString и рецепты, вызывающие ингредиенты, чтобы распечатать все это в хорошем маленьком формате. Когда я называю его на моем объекте" recipeOne "(который называется пицца Пепперони), я получаю "пицца Пепперони: 1,0 фунта теста, 8,0 унций соуса, 10,0 унций сыра"

Затем я приступаю к созданию объекта ресиппи и установил, что клон recipeOne, так что все хорошо отсюда...затем я меняю имя ressippi на "ананасовая Пицца", и это печатает прекрасно, но он не печатает 3 объекта ингредиента, которые recipeOne хранит, что он должен делать!

3 4

3 ответа:

Добавьте конструктор копирования в класс 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);
    }
}

Ингредиент.java

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;
    }
}

Как вы уже выяснили, реализация Cloneable на самом деле не клонирует объект. Вы должны будете реализовать метод clone() разумно, и если вы хотите глубокую копию, это то, что вы должны реализовать.

Теперь создание нового объекта Recipe с тем же атрибутом Name вполне нормально. И изменение имени для нового объекта после этого также вполне нормально, это не изменит имя первого объекта, поскольку java String неизменяемы.

Возможно, вы захотите взглянуть на commons-beanutils пакет, который предоставляет удобный код для клонирования объектов.

Наконец, что касается "...только передает ссылки...- ты бы почитал, например. эта и Эта нить.

Ура,

Сериализуйте его! Взгляните на функцию deepClone, как показано здесь: http://www.avajava.com/tutorials/lessons/how-do-i-perform-a-deep-clone-using-serializable.html

Другие ответы на неизменяемые строки, конечно, верны, но проблема, которую вы пытались описать с помощью примера строки, была просто плохим примером; более сложные объекты, такие как массив ингредиентов, все еще копируются по ссылке.

Также: измените имя массива так, чтобы оно не соответствовало имя класса (=путаница):

Ingredient Recipe[] = new Ingredient[INGREDIENT_ARRAY_MAX];