0

Say there is an EmployeeList that contains 5 Employee object.

I want to perform a clone of that EmployeeList to make a new EmployeeList, and I am wondering how should I do that?

So the following is my class Employee:

public class Employee {
private String name;
private String ssn;
private double salary;

private String name() {
    return name;
}

private void name(String name) {
    this.name = name;
}

private String ssn() {
    return ssn;
}

private void ssn(String ssn) {
    this.ssn = ssn;
}

private double salary() {
    return salary;
}

private void salary(double salary) {
    this.salary = salary;
}

void initialize(String initName, String initSsn, double initSalary) {
    this.name(initName);
    this.ssn(initSsn);
    this.salary(initSalary);
}

public Employee(String name, String ssn, double salary) {
    this.initialize(name, ssn, salary);
}

public Employee clone() {
    return new Employee(this.name, this.ssn, this.salary);
}
}

And the following is my class EmployeeList:

public class EmployeeList implements Cloneable {
private Employee[] list;
private int MAX = 5;

public EmployeeList() {
    list = new Employee[MAX];
    for (int i = 0; i < MAX; i++)
        list[i] = null;
}

public void add(Employee employee) {
    list[count] = employee;
}

public Object clone() {
    try {
        return super.clone();
    } catch (CloneNotSupportedException c) {
        System.out.println(c);
        return null;
    }
}   
}

I shorten the code so it`s easier to see.

My problem is:

When I performed the copy, I think that it copied the EmployeeList with pointers that points to the original Employee objects. Because when I change the original objects, the one in the new list changes as well

Is there anyway I can get that fixed?

Thank you very much.

Le Dude
  • 47
  • 1
  • 5

2 Answers2

1

yup, it did exactly what you thought it did - it cloned your array including its values. the array values in this case are pointers to instances of Employee, so you got a 2nd array pointing to the same Employees. its called a shallow copy. if you want a full copy you need something like

public Object clone() {
    try {
        EmployeeList copy = (EmployeeList) super.clone();
        if (list!=null) {
            copy.list = new Employee[list.length];
            for (int i=0; i<list.length; i++) {
                copy.list[i] = (Employee)list[i].clone();
            }
        } else {
            copy.list = null;
        }
        return copy;
    } catch (CloneNotSupportedException c) {
        System.out.println(c);
        return null;
    }
}

you will also need to make Employee clonable. generally when youre dealing with a graph of objects each object's clone() method needs to recursively clone its data members until you hit primitives (like your double) or immutable classes (classes that cannot be changed once constructed - like String in your case)

radai
  • 23,949
  • 10
  • 71
  • 115
  • So I made a Main class and inside of the class I wrote: `EmployeeList myList; myList = new EmployeeList(); employee1 = new Employee(); ..... EmployeeList newList; newList = (EmployeeList) myList.clone(); ` So that line returns a NullPointerException at `copy.list[i] =(Employee)list[i].clone();` – Le Dude Feb 10 '13 at 06:29
  • @WangZhongtian - updated the code to be a little more unll friendly. – radai Feb 10 '13 at 19:07
0

in your EmployeeList.cone(), insted of calling super.clone(), which does shallow copy, you should instead iterate over the list elements and called clone() on each Employee object, like pseudocode below:

EmployeeList.clone() {
   EmployeeList newList = (EmployeeList) super.clone();
   int i=0;
   for (Employee emp: this.list){
      newList[i++] = (Employee) emp.clone();
   }
   return newList;
}

Other option, without using Cloneable is to use Serializable interface and use a utility like Apache commons SerializationUtils to deep clone the object http://commons.apache.org/lang/api-2.3/org/apache/commons/lang/SerializationUtils.html#clone%28java.io.Serializable%29

Bimalesh Jha
  • 1,464
  • 9
  • 17
  • 1
    always use super.clone() when you can. prevents some nasty surprises when someone adds fields and forgets to update the clone() methods – radai Feb 10 '13 at 06:23