Object.clone()の性能
Objectにはclone()というメソッドが存在します。このメソッドは自身と同じ内容のオブジェクトを新たに生成してそれを返却します。
コピー元のオブジェクトが保持しているオブジェクトに関しては同一のものを参照するので、自分の頭の中のイメージとしてはオブジェクト用に確保した領域に対してmemcpyを行っているイメージ。
このメソッドはprotectedで実装されており、なおかつコピー元のオブジェクトがCloneableを実装してないとCloneNotSupportedExceptionを発生するのでちょっと使いにくい。
どのように使用するべきかの実装例を探してみたらいいのが見つかったので引用。
public class Foo implements Cloneable { public Object clone() { try { return (super.clone()); } catch (CloneNotSupportedException e) { throw (new InternalError(e.getMessage())); } } }
引用元:クローンナブル
コピーコンストラクタを作成してオブジェクトの複製を作成した場合との性能差が気になったので下記のようなテストクラスを作成して実行してみました。
public class TestClone implements Cloneable { private static final int SET = 10; private static final int ROOP = 100000; private int value1; private int value2; private int value3; public static void main(String[] args) { int i; long time; TestClone test = new TestClone(); for (int cycle = 0; cycle < SET; ++cycle) { time = System.nanoTime(); for (i = ROOP; i > 0; --i) { new TestClone(test); } System.out.println("COPY[" + cycle + "] " + (System.nanoTime() - time)); time = System.nanoTime(); for (i = ROOP; i > 0; --i) { test.clone(); } System.out.println("CLONE[" + cycle + "] " + (System.nanoTime() - time)); } } public Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { throw new InternalError(e.getMessage()); } } public TestClone() { value1 = 1; value2 = 2; value3 = 3; } public TestClone(TestClone src) { value1 = src.value1; value2 = src.value2; value3 = src.value3; } }
実行結果
COPY[0] 10954208 CLONE[0] 41769220 COPY[1] 2810436 CLONE[1] 38234045 COPY[2] 1876126 CLONE[2] 26948310 COPY[3] 1970632 CLONE[3] 27934632 COPY[4] 1601817 CLONE[4] 25787446 COPY[5] 1805355 CLONE[5] 25462086 COPY[6] 3114246 CLONE[6] 28914970 COPY[7] 1825418 CLONE[7] 26942646 COPY[8] 3111301 CLONE[8] 28188760 COPY[9] 1574968 CLONE[9] 26175436
…コピーコンストラクタの方が断然速い。
Object.clone()はnativeなのでnativeメソッド呼び出しに時間がかかっているのではないかと予測。
この結果を見てObject.clone()がさらに使いにくくなりました。