Gytis39 Gytis39 - 6 months ago 25
Java Question

How is cloning different from just assigning values (why bother implementing interface Cloneable)?

im trying to create a deep copy of a class. Here is the class im trying to copy and the last method is the copy one:

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


And here is the main:

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!!!!

}

}


The problem is as follows:

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)


You will notice that I am already cloning a product class object in the clone method of the catalog itself, but as you may notice the main class already tested it out and it works, so the cloning of the class product was successful.

Can you see the problem? I know there will also be a lot of minor mistakes of coding etiquette and maybe easier ways to do things, but im just a beginner. I have to implement deep copy, and it has to mean something, so cloning of the product class is not enough, I want to create a method for cloning an entire catalog, so if the machine was to be replaced with a newer one, you could just use that method.

By the way the entire project is creating a code for a virtual snack machine, like the ones where you enter money, press a number of the item you want, and then get it.

Thank you for your help!

Answer

Your exception is caused by this line:

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

It should be

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

But you really shouldn't be implementing your own deep clone like that. If you want a copy, create a separate method for it, or a copy constructor.

Comments