Effective Java Item 11 note

Override clone judiciously

Arwii
mycodingjourney
4 min readMay 29, 2018

--

看起來如果要override clone的話,大原則是如果要複製,那麼就要保證你要複製的class可以給出一個不是共用的內部field,以及該內部field也是一樣的原則。以避免變成都在改同一個物件但你不知道。然後要保證複製出來的object其內容是一樣的。

大致上非必要是不推薦使用clone的,下面會提到取代clone這種比較文件規範式的作法。

如果要使一個物件可以被複製,

  1. 需要implements Cloneable(這個interface裡面沒有任何method,所以才說是文件式的規範)
  2. 把protected Object clone() 改成(這也是自己要做的,從1.5開始有covariant return type,就是override method的return type可以是return subclass)

在Java裡面的規範是:

  1. x.clone() != x 是true
  2. x.clone().getClass() == x.getClass() 是true
  3. x.clone().equals(x) 是true
  4. 然後不使用constructor去建造出來

但都不是絕對的要求,只是希望而已。(所以沒辦法強迫接受它,只能自己注意它,所以不推薦使用)

然後底下是使用clone的一些建議,

  1. 跟constructor一樣,不要在建構的過程中,使用到新object裡面任何非final的method(item 17),避免call到override的method,導致兩個object的內容可能會不一樣
  2. 如果是繼承考量的class去override了clone,那麼就要跟Object.clone的行為是一樣。給要繼承的人可以有彈性。如果是implements了cloneable的class,那就要有個override public clone()
  3. 小心thread上面使用clone(),需要很好的sync

結論就是,除非你已經不得已要extends一個implements Cloneable的class,那你就只能去override clone,避免人家在extends你的class的時候有問題(文件規範的壞處)。

然後可以用底下兩個取代clone,如果可以的話,而且有很多好處,例如:不是文件規範的條件,不會與final field有衝突,不會丟出checked exception,不需要轉型。

P.S. 底下這個blog也有解釋到如果中間有個class沒有override好clone會發生什麼事。

https://blog.csdn.net/zhangjg_blog/article/details/18369201

--

--

Arwii
mycodingjourney

Try not to become a man of success, but rather try to become a man of value — A. Einstein