Java Q&A
Java 问答
Attack of the clones
克隆人的进攻
之 面向对象Java版
Time and space considerations in four different approaches to implementing deep clone() methods
权衡时间和空间的得失,有四种不同的方案来实现 deep clone() 方法。
K ][ N G of A R K™ 编译 [Revision 0.1]
January 24, 2003
二零零三年一月二十四日
Q:What are the advantages and disadvantages of implementing deep cloning via Java serialization and a built-in Object.clone() method from a performance point of view?
问:从性能的角度观之, 以 Java serialization(次第读写)或者内建的 Object.clone() 方法(method)来实现 deep cloning(深度克隆),各有哪些优劣之处?
A:Equipping classes in your application with correct clone() implementation is essential to many defensive programming patterns. Common examples include defensive copying of method parameters, cloning internal fields before returning them in getters, implementing immutability patterns, implementing containers with deep cloning semantics, and so on.
答:在您的应用程序中为各个类别搭载正确实现了的 clone() 方法,这对于许多防御式编程模式而言是至关重要的。常见的防御式编程模式包括:防御式的对方法接收的参数进行拷贝;从getters返回内部字段(field)之前先对该内部字段进行克隆;实现提供不可变功能的模式(immutability patterns);以 deep cloning(深度克隆)语义实现 containers(容器);等等。
Even though the question mentions just two possibilities, there are at least four distinct approaches to clone() implementation. In this Java Q&A installment, I consider design and performance tradeoffs involved in all of them.
尽管问题中只提到了两个可能的方案,其实至少有四种不同的方案来实现 clone() 方法。在本期的Java 问答中,我就针对这四种方案来进行设计和性能两方面的权衡。
Because cloning is so customizable, this article's examples will not necessarily translate directly to your own code; however, the general conclusions we will reach should provide useful guidelines in any application design.
由于克隆实现代码的可定制性很强,因此本文的示例代码不一定就适合直接转化到您自己的代码中;然而,我们得出的普适结论应该能为任何应用设计提供有用的指导。
Note the following disclaimer: What exactly constitutes a deep clone is debatable. Even though two objects can safely share the same String reference viewed as data, they cannot if the same field is used as an instance-scoped object monitor (such as when calling Object.wait()/notify() on it) or if field instance identity (such as when using the == operator) is significant to the design. In the end, whether or not a field is shareable depends on the class design. For simplicity, I assume below that all fields are used as pure data.
请注意这面这句不作承诺的声明:deep clone(深度克隆)究竟有哪些具体的实现要素,这个问题本身就具有争议性。尽管一个被视为数据的“String 引用”可以被两个对象安全的共享,但如果该 String 字段是被用作实体生存空间范围内(instance-scoped)的对象监视器(object monitor,比如对其调用 Object.wait()/notify() 的情形),或者字段实体的身份(identity)对于设计而言至关重要(比如使用 == operator 的情形),那么它就无法被安全的共享了。一言以蔽之,字段是否可被共享取决于类别的设计。为了简单起见,我假设本文所述的所有字段都被视为纯粹的数据来使用。
Performance measurements setup
用于性能度量的范例设定
Let's jump right into some code. I use the following simple hierarchy of classes as my cloning guinea pig:
让我们直接来看些代码。我使用如下简单的类别阶层体系来作为克隆“实验鼠”:
public class TestBaseClass
implements Cloneable, Serializable
{
public TestBaseClass (String dummy)
{
m_byte = (byte) 1;
m_short = (short) 2;
m_long = 3L;
m_float = 4.0F;
m_double = 5.0;
m_char = '6';
m_boolean = true;
m_int = 16;
m_string = "some string in TestBaseClass";
m_ints = new int [m_int];
for (int i = 0; i < m_ints.length; ++ i) m_ints [i] = m_int;
m_strings = new String [m_int];
m_strings [0] = m_string; // invariant: m_strings [0] == m_string
for (int i = 1; i < m_strings.length; ++ i)
m_strings [i] = new String (m_string);
}
public TestBaseClass (final TestBaseClass obj)
{
if (obj == null) throw new IllegalArgumentException ("null input: obj");
// Copy all fields:
m_byte = obj.m_byte;
m_short = obj.m_short;
m_long = obj.m_long;
m_float = obj.m_float;
m_double = obj.m_double;
m_char = obj.m_char;
m_boolean = obj.m_boolean;
m_int = obj.m_int;
m_string = obj.m_string;
if (obj.m_ints != null) m_ints = (int []) obj.m_ints.clone ();
if (obj.m_strings != null) m_strings = (String []) obj.m_strings.clone ();
}
// Cloneable:
public Object clone ()
{
if (Main.OBJECT_CLONE)
{
try
{
// Chain shallow field work to Object.clone():
final TestBaseClass clone = (TestBaseClass) super.clone ();
// Set deep fields:
if (m_ints != null)
clone.m_ints = (int []) m_ints.clone ();
if (m_strings != null)
clone.m_strings = (String []) m_strings.clone ();
return clone;
}
catch (CloneNotSupportedException e)
{
throw new InternalError (e.toString ());
}
}
else if (Main.COPY_CONSTRUCTOR)
return new TestBaseClass (this);
else if (Main.SERIALIZATION)
return SerializableClone.clone (this);
else if (Main.REFLECTION)
return ReflectiveClone.clone (this);
else
throw new RuntimeException ("select cloning method");
}
protected TestBaseClass () {} // accessible to subclasses only
private byte m_byte;
private short m_short;
private long m_long;
private float m_float;
private double m_double;
private char m_char;
private boolean m_boolean;
private int m_int;
private int [] m_ints;
private String m_string;
private String [] m_strings; // invariant: m_strings [0] == m_string
} // end of class
public final class TestClass extends TestBaseClass
implements Cloneable, Serializable
{
public TestClass (String dummy)
{
super (dummy);
m_int = 4;
m_object1 = new TestBaseClass (dummy);
m_object2 = m_object1; // invariant: m_object1 == m_object2
m_objects = new Object [m_int];
for (int i = 0; i < m_objects.length; ++ i)
m_objects [i] = new TestBaseClass (dummy);
}
public TestClass (final TestClass obj)
{
// Chain to super copy constructor:
super (obj);
// Copy all fields declared by this class:
m_int = obj.m_int;
if (obj.m_object1 != null)
m_object1 = ((TestBaseClass) obj.m_object1).clone ();
m_object2 = m_object1; // preserve the invariant
if (obj.m_objects != null)
{
m_objects = new Object [obj.m_objects.length];
for (int i = 0; i < m_objects.length; ++ i)
m_objects [i] = ((TestBaseClass) obj.m_objects [i]).clone ();
}
}
// Cloneable:
public Object clone ()
{
if (Main.OBJECT_CLONE)
{
// Chain shallow field work to Object.clone():
final TestClass clone = (TestClass) super.clone ();
// Set only deep fields declared by this class:
if (m_object1 != null)
clone.m_object1 = ((TestBaseClass) m_object1).clone ();
clone.m_object2 = clone.m_object1; // preserve the invariant
if (m_objects != null)

博客聚焦Java领域,探讨了实现deep clone()方法的相关内容。权衡时间和空间得失,提出了四种不同的实现方案,为Java开发者在处理对象克隆问题上提供了思路。

1542

被折叠的 条评论
为什么被折叠?



