1

I'm trying to get a clone of an object using copy-contructor, unfortunately seems that all the modification to the clone are reflected to the original object.

I have this interface

public interface Car{
     public Car newInstance(Car c);
}

and various Object hat implements the interface in this way

public FerrariSpyder implements Car{
    String name;
    String description
    ArrayList<Feature> featureList;

    public FerrariSpyder(String name, String description, ArrayList<Feature> featureList){
      this.name=name;
      this.descripion=descripion;
      this.featureList=featureList;
    }

    @Override
    public Car newInstance(Car c) {
        return FerrariSpyder.newInstance((FerrariSpyder) c);
    }

    public static FerrariSpyder newInstance(FerrariSpyder fs) {
        return new FerrariSpyder(fs.getName(), fs.getDescription(), fs.getFeatureList());
    }

}

Now assuming that I have a Car object named originalCar I try to clone this with

Car clone=originalCar.newIstance(originalCar);

If I add elements in featureList of the clone also the featureList in originalCar will be modified.

AndreaF
  • 11,975
  • 27
  • 102
  • 168

1 Answers1

3

You create a new instance of your object, but the fields are shared.

Concerning name and description, there is no problem, because Java treat Strings as immutable. If you try to "modify" them, you will in fact change the reference to them.

Concerning featureList, that's another story. You currently have the same list instance in both objects. You need to create a new instance of the list when you call the constructor of your new object, like this:

public static FerrariSpyder newInstance(FerrariSpyder fs) {
    return new FerrariSpyder(fs.getName(), fs.getDescription(), new ArrayList<>(fs.getFeatureList()));
}

Note: Be careful, there are now 2 lists, but they share the same objects. This means 2 things:

  • If you modify a Feature in one of the lists, you'll see modifications of that Feature in the other list.
  • If you add/remove an object from one list, the other list will not be affected.

If you want to be able to modify the Feature objects in the lists without affecting the other list, you'll have to do deep copies of these objects as well.


Side note: What you are doing here is basically writing a clone() method, which you named newInstance(). You should probably implement the Cloneable interface to do it the Java way ;-)

Joffrey
  • 32,348
  • 6
  • 68
  • 100
  • and deep copies of the features. – njzk2 Apr 23 '14 at 15:29
  • Thanks for the answer I'll go to try your suggestion. I'm try this because I have heard that native clone mehod is riskful in this discussion http://stackoverflow.com/questions/2427883/clone-vs-copy-constructor-which-is-recommended-in-java I would be happy to know your opinion about this – AndreaF Apr 23 '14 at 15:43
  • @AndreaF Very interesting discussion. I would personally stick with `clone()` because of hierarchy reasons raised in that post: http://stackoverflow.com/a/5026085/1540818 – Joffrey Apr 23 '14 at 16:05
  • @AndreaF On the other hand, on has to be careful. If you want to use clone, you have to implement it properly in every class of the class hierarchy up to Object. – Joffrey Apr 23 '14 at 16:08