Чем клонирование отличается от простого присвоения значений (зачем реализовывать интерфейс Cloneable)?

я пытаюсь создать глубокую копию класса. Вот класс, который я пытаюсь скопировать, и последний метод - это копирование:

import java.util.ArrayList;
import java.util.List;

public class catalog implements Cloneable{

    List<product> cat = new ArrayList<>();
    int counter;
    final int capacity = 2;

    public void addProduct(product x){
        cat.add(x);
    }
    public void addProduct(String name, int id, int price, int stock) throws Exception{
        for(int i = 0; i < cat.size(); i++){
                product temp = cat.get(i);
                if(temp.name == name){
                    temp.stock = temp.stock + stock;
                    return;
                }
                if(temp.id == id){
                    System.out.println("Product with this ID already exists");
                    return;
                }
        }
        if(cat.size() >= capacity){
            //throw new customException("Not enough capacity");
            throw new customException();
        }
        product temp = new product();
        temp.name = name;
        temp.id = id;
        temp.price = price;
        temp.stock = stock;
        cat.add(temp);
        }
    public void showSelection(){
        for(product temp : cat){
            System.out.println("Product " + temp.name + " ID: " + temp.id
                    + " Price: " + temp.price + " In stock: " + temp.stock);
        }
    }
    public void removeFromStock(String name){
        for(int i = 0; i < cat.size(); i++){
            product temp = cat.get(i);
            if(temp.name == name){
                temp.stock = temp.stock - 1;
                cat.set(i, temp);
            }
        }
    }

    public Object clone(){
        catalog b = new catalog();
        for(int i = 0; i <= cat.size(); i++){
            product temp, temp1;
            temp1 = cat.get(i);
            temp = (product)temp1.clone();
            b.addProduct(temp);
        }
        return b;
    }
}

И вот основное:

public class testMoney {

    public static void main(String[] args) {

        automatasklase test = new automatasklase();
        test.addMoney(50);
        System.out.println(test.getMoney());
        product cola = new product();
        cola.id = 1;
        cola.price = 2;
        cola.name = "Cola";
        productsExpire Milk = new productsExpire();
        Milk.name = "Milk";
        Milk.id = 2;
        Milk.price = 10;
        Milk.stock = 10;
        Milk.isExpired = true;
        catalog menu = new catalog();
        menu.addProduct(cola);
        menu.addProduct(Milk);
        menu.showSelection();
        try{
        menu.addProduct("Pepsi" ,3, 5, 108);
        }catch(Exception e){
            System.out.println("Exception occured = " +e);
        }
        try {
            menu.addProduct("Cola", 1, 3, 7);
        } catch (Exception e) {
            System.out.println("Exception occured = " + e.getMessage());
        }
        menu.showSelection();
        test.buyProduct(menu, 2);
        System.out.println(test.getMoney());
        menu.showSelection();
        Milk.isAvailable();
        product copyy = (product)cola.clone();
        System.out.println("-------------");
        System.out.println(cola.id + cola.name + cola.price + cola.stock);
        System.out.println(copyy.id + copyy.name + copyy.price + copyy.stock);

        // BELOW THE PROBLEM OCCURS!!!

        catalog newtest = (catalog) menu.clone();

        // ABOVE THE IS THE PROBLEM!!!!

    }

}

Проблема заключается в следующем:

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 2, Size: 2
    at java.util.ArrayList.rangeCheck(Unknown Source)
    at java.util.ArrayList.get(Unknown Source)
    at AutomatasA.catalog.clone(catalog.java:58)
    at AutomatasA.testMoney.main(testMoney.java:46)

Вы заметите, что я уже клонирую объект класса продукта в методе clone самого каталога, но, как вы можете заметить, основной класс уже протестировал его, и он работает, поэтому клонирование продукта класса прошло успешно.

Вы видите проблему? Я знаю, что также будет много мелких ошибок этикета кодирования и, возможно, более простых способов сделать что-то, но я всего лишь новичок. Я должен реализовать глубокую копию, и это должно что-то означать, поэтому клонирования класса продукта недостаточно, я хочу создать метод для клонирования всего каталога, поэтому, если машина должна была быть заменена на более новую, вы может просто использовать этот метод.

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

Спасибо за помощь!


person Gytis39    schedule 18.05.2016    source источник
comment
Не используйте клонирование, если вам нужна глубокая копия.   -  person shmosel    schedule 18.05.2016
comment
Почему? Я хожу на курсы на родном языке, и оба метода называются одинаково. В чем разница между ними?   -  person Gytis39    schedule 18.05.2016


Ответы (1)


Ваше исключение вызвано этой строкой:

for(int i = 0; i <= cat.size(); i++){

Так должно быть

for(int i = 0; i < cat.size(); i++){

Но вам действительно не следует реализовывать свой собственный глубокий клон таким образом. Если вам нужна копия, создайте для нее отдельный метод или конструктор копирования.

person shmosel    schedule 18.05.2016
comment
Спасибо, это полностью решило мою проблему! Но вы сказали, что я должен создать для него отдельный метод, разве я этого не делаю? Я делаю копирование методом клонирования. - person Gytis39; 18.05.2016
comment
@ Gytis39 Вы переопределяете Object.clone() , который по соглашению должен создавать свою копию через super.clone(). Ваш метод этого не делает, а это значит, что нет причин переопределять метод clone() или даже реализовывать Cloneable. - person shmosel; 18.05.2016