简体   繁体   中英

Understanding what happens when we override the clone method with and without invoking super.clone?

I'm reading Effective Java by Joshua Bloch. I must say its a dense and complex book. The chapter on Methods Common to all objects (chapter 3) is proving hard for me to grasp as I've been programming for less than 3 years (1 year in java). I don't quite understand the concept of overriding the clone method appropriately. Can I get a simple to follow example of implementing clone, the right way as well as the wrong way? And why failing to invoke super.clone would cause a problem? what will happen?

Thank you in advance.

I'm reading that book myself. Not sure if I did everything "right" in this example, but maybe it'll help you understand.

Computer.java

package testclone;

public class Computer implements Cloneable {
    String OperatingSystem;

    protected Computer Clone() throws CloneNotSupportedException {
        Computer newClone = (Computer) super.clone();
        newClone.OperatingSystem = this.OperatingSystem;
        return newClone;
    }

}

MultiCore.java

package testclone;

public class MultiCore extends Computer implements Cloneable {
    int NumberOfCores;

    @Override
    protected MultiCore Clone() throws CloneNotSupportedException {
     //*********  use 1 of the next 2 lines  ***********           
        //MultiCore newClone = (MultiCore) super.clone();
        MultiCore newClone = new MultiCore();
        newClone.NumberOfCores = this.NumberOfCores;
        return newClone;
    }
}

TestClone.java

package testclone;

public class TestClone implements Cloneable {

    public static void main(String[] args) throws CloneNotSupportedException {
        //Computer myComputer = new Computer();
        //myComputer.OperatingSystem = "Windows";

        MultiCore myMultiCore = new MultiCore();
        myMultiCore.OperatingSystem = "Windows";    //field is in parent class
        myMultiCore.NumberOfCores = 4;

        MultiCore newMultiCore = myMultiCore.Clone();

        System.out.println("orig Operating System  = " + myMultiCore.OperatingSystem);
        System.out.println("orig Number of Cores   = " + myMultiCore.NumberOfCores);
        System.out.println("clone Operating System = " + newMultiCore.OperatingSystem);
        System.out.println("clone Number of Cores  = " + newMultiCore.NumberOfCores);

    }

}

Output:

orig Operating System = Windows

orig Number of Cores = 4

clone Operating System = null * This line is not what you want.

clone Number of Cores = 4

If you use the super.clone() line instead, then the Output is

orig Operating System = Windows

orig Number of Cores = 4

clone Operating System = Windows * Now it's what you want

clone Number of Cores = 4

So if you don't use super.clone(), it doesn't clone the fields in the parent (or grandparent, or great-grandparent, etc)

Good luck! (Sorry - the above looked formatted correctly when I typed it in, but for some reason looks awful when it actually shows)

You should always use super.clone() . If you don't, and say just return new MyObject(this.x); , then that works fine for instances of MyObject. But if someone extends MyObject, it's no longer possible for them to get an instance of the right class when overriding your clone method. The one thing Object.clone does that you can't do a good job of yourself is creating an instance of the right class; the rest is just copying instance fields, which is drudgework you could have done yourself if you wanted.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM