Effective Java: Analysis of the clone() method

北战南征 提交于 2019-11-27 01:50:59

问题


Consider the following from Effective Java Item 11 (Override clone judiciously) where Josh Bloch is explaining what is wrong with the clone() contract .

There are a number of problems with this contract. The provision that “no constructors are called” is too strong. A well-behaved clone method can call constructors to create objects internal to the clone under construction. If the class is final, clone can even return an object created by a constructor.

Can someone explain what Josh Bloch is saying in the first paragraph by "If the class is final, clone can even return an object created by a constructor." What does final have to do with clone() here?


回答1:


If a class is not final, clone has to return the most derived class for which it was called. That can't work with a constructor, because clone doesn't know which one to call. If a class is final, it can't have any subclasses, so there's no danger in calling its constructor when cloning.




回答2:


It's because typical implementations of clone() look like this:

public class MyClass implements Cloneable {
  protected Object clone() {
    MyClass cloned = (MyClass) super.clone();
    // set additional clone properties here
  }
}

In this way you can inherit the cloning behavior from your superclass. It's widely assumed that the result of a clone() operation will return the correct instance type based on the object it was called on. Ie. this.getClass()

So if a class is final, you don't have to worry about a subclass calling super.clone() and not getting the right object type back.

public class A implements Cloneable {
    public Object clone() {
       return new A();
    }
}


public class B extends A {
    public Object clone() {
       B b = (B)super.clone(); // <== will throw ClassCastException
    }
}

But, if A is final, no one can extend it, and thus it's safe to use a constructor.




回答3:


A class doesn't have to provide its own implementation of clone in order to be cloneable. It can delegate that to its cloneable superclass. Here comes the catch: clone must always return an instance of the same class as the instance it is called on. That is impossible to achieve in the described case if an explicit constructor is called. If the class overridng clone is final, on the other hand, this would be fine.




回答4:


The contract for clone specifies that "By convention, the returned object should be obtained by calling super.clone". If your class is not final and you return something obtained with a constructor invocation, calling super.clone() from a subclass will not return the expected result (first of all, the type of the returned object will not be the type of the subclass, as the native clone() method would return).




回答5:


See Jorado answer. This is the explanation. In additional clone has problem in final fields see : http://en.wikipedia.org/wiki/Clone_%28Java_method%29#clone.28.29_and_final_fields

You also should read Josh interview on clone in: http://www.artima.com/intv/bloch13.html



来源:https://stackoverflow.com/questions/11540792/effective-java-analysis-of-the-clone-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!