この記事では、次の4つの問題について説明します
1。Javaクローン可能なインターフェイスは、深いコピーを実装します
2。Javaのシリアル化は深いコピーを実装します
3.最速のディープコピーバイナリライブラリクローニングソースコード分析
4。いくつかのコピー方法の速度の比較
この記事では、ディープコピーの概念については説明しません。 C ++にディープコピーを実装します。一般に、割り当て演算子 "="を過負荷にして、同じクラスのオブジェクト間でディープコピーを実装します。したがって、Javaでは、関数内のオブジェクトの各プロパティを割り当てるコピー関数を定義することもできます。この方法はシンプルで自然ですが、致命的な問題があります。ある日、クラスに深いコピーを必要とする新しい属性がクラスに追加される場合、対応するコピー関数も変更する必要があります。この方法は、クラスの拡張性に大きな不便をもたらします。この問題を解決する方法は、第1章、第2章、第3章の実装方法とセクション4の速度テストを見てみましょう。
1. Javaクローン可能なインターフェイスは、ディープコピー<br />を実装します。このようにして、クラスはcolnableインターフェイスクローン関数を実装し、クローン関数のsuper.cloneを呼び出す必要があります。この方法のこの深いコピーも別の問題をもたらします。クラスのプロパティとして他のクラスのオブジェクトがある場合、他のクラスもクローン可能なインターフェイスに過負荷と実装する必要があります。これが例です。次の例では、complexDoにはsimpledoオブジェクトが含まれています。 ComplexDo Deepコピーを実装するには、最初にSimpledoのクローンインターフェイスを実装する必要があります。
パブリッククラスのsimpledoは、クローン可能、シリアル化可能な{private int x = 1;プライベート文字列s = "simpledo"; @Override保護されたオブジェクトclone()throws clonenotsuptedexception {simpledo newclass =(simpledo)super.clone(); NewClassを返します。 }} public class complexDoは、クローン可能、シリアル化可能な{private int x = 1;プライベート文字列s = "complex";プライベート整数a = 123;プライベート整数B = 1234;プライベート整数C = 1334455;プライベート文字列s2 = "hehehe";プライベート文字列s3 = "hahaha";プライベートロングID = 1233245L; private arrayList <simpledo> l = new arrayList <simpledo>(); @Override public object clone()throws clonenotsupportedexception {complexDo newclass =(complexDo)super.clone(); newclass.l = new ArrayList <Simpledo>(); for(simpledo simple:this.l){newclass.l.add((simpledo)simple.clone()); } newClassを返します。 }}多くの記事は、文字列タイプの割り当て演算子は深いコピーであると言っていることに注意する必要がありますが、実際、Javaで割り当てオペレーターを使用している人は浅いコピーですが、なぜこのような明らかなエラーを持つ記事がこれが深いコピーであると言わざるを得ないのですか?私の理解では、文字列とタイプの属性は基本的なタイプであり、提供される方法は、内部データの変更が設計されている限り、新しいオブジェクトになります。したがって、文字列操作は、当初指定されていたメモリに影響しません。したがって、一般的に言えば、文字列などの基本クラスの割り当て操作は深いコピーです。
このため、String String Splicingを使用する場合、新しいメモリを開く必要があるため、StringBuilderは組み込みのCharアレイ範囲が十分ではない場合に大きなメモリを再適用するため、StringBuilderのみがより大きなメモリを再適用するため、多くの人はStringBuilderの代わりにStringBuilderを使用することをお勧めします。スプライシングとは反対のトリミングには、文字列にサブストリング関数があります。サブストリング関数を使用する場合、新しい文字列の内部char配列は元の文字列と同じですか?これはもっと面白いです。興味がある場合は、JDK1.6とJKD1.7の実装を比較して確認できます。
2。Javaのシリアル化は深いコピーを実装します
この方法の原則は、Javaシリアル化を使用してオブジェクトをバイナリバイトストリームにシリアル化し、その後、値をオブジェクトに割り当てて割り当てることです。コード例:
public Object seircopy(object src){try {bytearrayoutputStream byteout = new bytearrayoutputStream(); objectOutputStream out = new objectOutputStream(byteout); out.writeObject(src); bytearrayinputStream bytein = new bytearrayinputStream(byteout.tobytearray()); ObjectInputStream in = new ObjectInputStream(bytein); Object Dest = in.readObject(); DESTを返す; } catch(例外e){//エラーハンドラーを返すnullを実行します。 }}もちろん、JSONやその他のシリアル化ライブラリを使用して、シリアル化を完了することもできます。この方法は、クローネーベル界面の拡張可能な欠点を効果的に回避します。関数は基本的にすべてのクラスに適しています。欠点は、それが相対的なメモリコピーであることです。シリアル化には、最初にオブジェクトをバイナリバイトストリームに変換し、次にバイナリバイトストリームをオブジェクトメモリの一部に再コーピングする必要があります。これは比較的遅いです。
3.最速のディープコピーバイナリライブラリクローニングソースコード分析
ソースコードでは、コア処理ロジックはクローナークラスにあります。
2つの再帰的なリンクがあります。
(1)では、FastCloneはIfastCloneインターフェイスクラスから継承されたオブジェクトを完成させます。つまり、すべてコレクション操作のコピーです。
(2)では、cloneObjectは、反射メカニズムを介して通常のオブジェクトの各プロパティを取得し、objenesisを使用して新しく生成されたオブジェクトのプロパティに値を割り当てるプロセスを完了します。
この方法は非常に拡張可能です。既存のコードに頼って深いコピーを完了することができるだけでなく、クローニングを必要としないいくつかのクローニング方法とタイプを定義することもできます。これは非常に柔軟です。
4。いくつかのコピー方法の速度の比較
上記の3つのモードを使用して、深いコピーを完了することができ、最速のコピー方法は私たちが気にするものです。
最初に、コードをテストします。
public void testcloneComplex()は、clonenotsupportedexceptionをスローします{final int copycount = 1; List <ComplexDo> complexDolist = new ArrayList <ComplexDo>(Copycount * 3); final complexDo complex = new ComplexDo(); //両側ライブラリの計算long start = system.currenttimemillis(); for(int i = 0; i <copycount; ++ i){final complexdo deepclone = clner.deepclone(complex); complexDolist.Add(deepclone); } long end = system.currenttimemillis(); system.out.println( "deepclone cost time =" +(end-start)); //クローン可能なインターフェイスによって実装されたクローン関数を呼び出すstystem.currenttimemillis(); for(int i = 0; i <copycount; ++ i){final complexDo interfaceClone =(complexDo)complen.clone(); complexDolist.Add(InterfaceClone); } end = system.currenttimemillis(); system.out.println( "interfacecloneコスト時間=" +(end-start)); //シリアル化と降下化は新しいオブジェクトを生成しますfor(int i = 0; i <copycount; ++ i){final complexdo seirclone = seircopy(complex); complexDolist.Add(Seirclone); } end = system.currenttimemillis(); System.out.println( "Seirclone Cost Time =" +(end-start)); }実行結果の単位はミリ秒です(このデータは無視され、Javaホットスポットと可能なGCを計算しません)。
この表から、結論を描くことができます。
1.クローン可能なインターフェイスのコピーは、メモリコピーのみを含むため、最速ですが、関係する属性がより一般的なオブジェクトである場合、書くのは少し面倒です。
2。シリアル化/脱介入コピーは最も遅いです
3.クローニングライブラリを使用すると、再帰および反射メカニズムのコピーは、クローン可能なインターフェイスの実装よりも遅くなりますが、シリアル化方法よりも速いです。
上記はこの記事に関するものです。すべての人の学習に役立つことを願っています。