博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Effective Java 11 Override clone judiciously
阅读量:4987 次
发布时间:2019-06-12

本文共 5514 字,大约阅读时间需要 18 分钟。

Principles

  1. If you override the clone method in a nonfinal class, you should return an object obtained by invoking super.clone
  2. In practice, a class that implements Cloneable is expected to provide a properly

    functioning public clone method.

  3. Never make the client do anything the library can do for the client.
  4. The clone architecture is incompatible with normal use of final fields referring to mutable objects

   

Creates and returns a copy of this object. The precise meaning of "copy" may depend on the class of the object.

   

The general intent is that, for any object x, the expression

x.clone() != x will be true,

x.clone().getClass() == x.getClass() will be true,

but these are not absolute requirements. While it is typically the case that

x.clone().equals(x) will be true,

this is not an absolute requirement. Copying an object will typically entail creating a new instance of its class, but it may require copying of internal data structures as well. No constructors are called.

   

The return type of the method is subclass instead of the super class which means this is applied with covariant which is introduced from JRE 1.5. As the code shown below:

   

@Override public PhoneNumber clone() {

try {

return (PhoneNumber) super.clone();

} catch(CloneNotSupportedException e) {

throw new AssertionError(); // Can't happen

}

}

   

import java.util.Arrays;

import java.util.EmptyStackException;

   

public class Stack implements Cloneable {

private Object[] elements;

private int size = 0;

private static final int DEFAULT_INITIAL_CAPACITY = 16;

   

public Stack() {

this.elements = new Object[DEFAULT_INITIAL_CAPACITY];

}

   

public void push(Object e) {

ensureCapacity();

elements[size++] = e;

}

   

public Object pop() {

if (size == 0)

throw new EmptyStackException();

Object result = elements[--size];

elements[size] = null; // Eliminate obsolete reference

return result;

}

   

// Ensure space for at least one more element.

private void ensureCapacity() {

if (elements.length == size)

elements = Arrays.copyOf(elements, 2 * size + 1);

}

   

@Override

protected Object clone() throws CloneNotSupportedException {

try {

Stack result = (Stack) super.clone();

// Do recursive clone with a class.

result.elements = elements.clone();

return result;

} catch (CloneNotSupportedException e) {

throw new AssertionError();

}

}

}

   

Implement clone with recursive clone method.

   

public class Hashtable implements Cloneable {

private Entry[] buckets = new Entry[3];

   

private static class Entry {

final Object key;

Object value;

Entry next;

   

Entry(Object key, Object value, Entry next) {

this.key = key;

this.value = value;

this.next = next;

}

   

// Recursively copy the linked list headed by this Entry

Entry deepCopy() {

return new Entry(key, value, next == null ? null : next.deepCopy());

}

   

@Override

public String toString() {

return String.format("[key: %d, value: %s, next: %s]", key, value,

next);

}

}

   

public static void main(String[] args) {

Hashtable ht = new Hashtable();

Entry previous = null;

   

for (int i = 0; i < 3; i++) {

Entry e = new Entry(i, "v" + i, previous);

ht.buckets[i] = e;

}

   

Hashtable newHt = ht.clone();

newHt.buckets[newHt.buckets.length - 1] = new Entry(

newHt.buckets[newHt.buckets.length - 1].key,

newHt.buckets[newHt.buckets.length - 1].value

+ String.valueOf(1),

newHt.buckets[newHt.buckets.length - 1].next);

System.out.println("newHt");

for (int i = 0; i < newHt.buckets.length; i++) {

System.out.println(newHt.buckets[i]);

}

System.out.println("ht");

for (int i = 0; i < ht.buckets.length; i++) {

System.out.println(ht.buckets[i]);

}

}

   

@Override

public Hashtable clone() {

try {

Hashtable result = (Hashtable) super.clone();

result.buckets = new Entry[buckets.length];

for (int i = 0; i < buckets.length; i++)

if (buckets[i] != null)

result.buckets[i] = buckets[i].deepCopy();

return result;

} catch (CloneNotSupportedException e) {

throw new AssertionError();

}

}

}

   

To prevent a stack overflow caused by the lengthy stack frame for each element in the list from happening. We can implement the code like this below:

   

// Iteratively copy the linked list headed by this Entry

Entry deepCopy() {

Entry result = new Entry(key, value, next);

for (Entry p = result; p.next != null; p = p.next)

p.next = new Entry(p.next.key, p.next.value, p.next.next);

return result;

}

   

Summary

  1. Like a constructor, a clonemethod should not invoke any nonfinal methods on the clone under construction ().
  2. Object's clone method is declared to throw CloneNotSupportedException, but overriding clone methods can omit this declaration. But if the subclass overrides its superclass's clone method it should be declared as proteteced and throw CloneNotSupportedException and the class should not implment Cloneable.
  3. To make a thread-safe class implement Cloneable you must ensure its clone method be synchronized just like other methods.
  4. Class which implement Cloneable should override clone with public method return itself.
    1. First call super.clone.
    2. Fix any fields that is not primitive or immutable type object.
      1. Call the field's clone method recursively.
      2. Handle the exception case that if the object represent a unique ID or serial number or creating time even if they are primitive type or a reference to immutable object.
  5. If it's not appropriate way to provide an alternative means of object coping or simply not providing the capability of cloneable(such as immutable class) then just provide a copy constructor or copy factory.
    1. Public Yum(Yum yum);
    2. Public static Yum newInstance(Yum yum);

         

   

   

转载于:https://www.cnblogs.com/haokaibo/p/override-clone-judiciously.html

你可能感兴趣的文章
HDOJ-1013
查看>>
A. Bus to Udayland
查看>>
Python 基础篇:字典、集合、文件操作
查看>>
Jmail发送邮件与带附件乱码解决办法
查看>>
分治法求一个N个元素数组的逆序数
查看>>
P4149 [IOI2011]Race
查看>>
SimpleDateFormat函数语法
查看>>
140705
查看>>
HDOJ 1427(dfs) 速算24点
查看>>
Day-08 文件操作
查看>>
个人使用angular的一些小总结
查看>>
webservice wsdl axis2报错 Provider com.bea.xml.stream.MXParserFactory not found
查看>>
EOS1.1版本新特性介绍
查看>>
929. Unique Email Addresses
查看>>
3.常见的ORM框架
查看>>
Hdu 1326 Box of Bricks
查看>>
常用数据结构算法 : 堆排序
查看>>
Highcharts X轴名称太长,如何设置下面这种样式
查看>>
使用模板类,创建树。使用头文件分离模板类的申明与实现时出错
查看>>
王者的世界:全球十大对冲基金公司传奇
查看>>