How to clone a Java object with the clone() method

2019-02-16 06:59发布

I don't understand the mechanism of cloning custom object. For example:

public class Main{

    public static void main(String [] args) {

        Person person = new Person();
        person.setFname("Bill");
        person.setLname("Hook");

        Person cloned = (Person)person.clone();
        System.out.println(cloned.getFname() + " " + cloned.getLname());
    }
}

class Person implements Cloneable{

    private String fname;
    private String lname;

    public Object clone() {

        Person person = new Person();
        person.setFname(this.fname);
        person.setLname(this.lname);
        return person;
    }

    public void setFname(String fname) {
        this.fname = fname;
    }

    public void setLname(String lname){
        this.lname = lname;
    }

    public String getFname(){
        return fname;
    }

    public String getLname() {
        return lname;
    }
}

This is example shows right way of cloning as a in the books write. But I can delete implements Cloneable in the class name definition and I receive the same result.

So I don't understand the proposing of Cloneable and why clone() method is defined in class Object?

标签: java clone
8条回答
女痞
2楼-- · 2019-02-16 07:13

clone is not mature as Joshua bloch say:

http://www.artima.com/intv/bloch13.html

查看更多
聊天终结者
3楼-- · 2019-02-16 07:18

It's the same purpose as any such interface. Primarily it allows methods (etc.) to accept ANY Clonable object and have access to the method they need without limiting themselves to one specific object. Admittedly Clonable is probably one of the less useful interfaces in this respect, but there's certainly places where you might want it. If you want more of an idea consider the interface Comparable which for example allows you to have sorted lists (because the list doesn't need to know what the object is, only that they can be compared).

查看更多
趁早两清
4楼-- · 2019-02-16 07:18

if you dont declare cloneable interface you should be getting CloneNotSupportException when you call clone method.If you declare and then call clone method it will make shallow copy.

查看更多
太酷不给撩
5楼-- · 2019-02-16 07:28

There's no need to create the object explicitly here in clone() method. Just by calling super.clone() will create the copy of this object. It will perform the shallow clone.

查看更多
仙女界的扛把子
6楼-- · 2019-02-16 07:30

In your example you are not doing actual cloning.you are overridden the clone() method of object class and given your own implementation. but in your clone method you are creating a new Person object. and returning it.So in this case the actual object is not cloned.

So your clone method should be like :

public Object clone() {
      return super.clone();
  }

So here clone will be handled by superclass method.

查看更多
Viruses.
7楼-- · 2019-02-16 07:33

The clone method is meant to make a deep copy. Make sure you understand the difference between deep and shallow copies. In your case a copy constructor may be the pattern you want. In some cases you can't use this pattern however, for example because you're subclassing class X and you don't have access to the constructor of X that you need. If X overrides its clone method correctly (if necessary) then you could make a copy in the following way:

class Y extends X implements Cloneable {

    private SomeType field;    // a field that needs copying in order to get a deep copy of a Y object

    ...

    @Override
    public Y clone() {
        final Y clone;
        try {
            clone = (Y) super.clone();
        }
        catch (CloneNotSupportedException ex) {
            throw new RuntimeException("superclass messed up", ex);
        }
        clone.field = this.field.clone();
        return clone;
    }

}

In general when overriding your clone method:

  • Make the return type more specific
  • Start with calling super.clone()
  • Do not include throws clause when you know clone() will also work for any subclass (weakness of the clone-pattern; make class final if possible)
  • Leave immutable and primitive fields alone, but clone mutable object fields manually after the call to super.clone() (another weakness of the clone-pattern, since these fields cannot be made final)

The clone() method of Object (which will eventually be called when all superclasses obey the contract) makes a shallow copy and takes care of the correct runtime type of the new object. Note how no constructor is called in the entire process.

If you want to be able to call clone() on instances, then implement the Cloneable interface and make the method public. If you don't want to be able to call it on instances, but you do want to make sure subclasses can call their super.clone() and get what they need, then don't implement Cloneable and keep the method protected if your superclass hasn't declared it public already.

The clone pattern is difficult and has a lot of pitfalls. Be sure it's what you need. Consider copy constructors, or a static factory method.

查看更多
登录 后发表回答