Alibaba の面接官の質問:
Java のディープ クローン作成とシャロー クローン作成についての理解を話してください
回答:
(注: この記事は、ディープ クローニングとシャロー クローニングの違いと実装方法について説明しています?)
話は安いです
#私はこれまでに、ディープ クローニングとシャロー クローニング (ディープ コピー、シャロー コピー) に遭遇したことがあります。最近一度質問したのですが、クローン方法があるという印象以外、混乱しています! ! !クローン作成 (コピー) は、オブジェクトのコピーを迅速に取得する Java の一般的な操作です。クローン作成はディープ クローン作成とシャロー クローン作成に分けられます。
浅いクローン: 新しいオブジェクトを作成します。新しいオブジェクトのプロパティは、元のオブジェクトとまったく同じです。非基本型プロパティの場合、それらは依然として、ポイントされているオブジェクトのメモリ アドレスを指します。元のプロパティによる。
ディープ クローン作成: 新しいオブジェクトを作成すると、属性で参照されている他のオブジェクトもクローン化され、元のオブジェクト アドレスを指さなくなります。
つまり、ディープ クローン作成とシャロー クローン作成はどちらもヒープ内に新しい領域を割り当てますが、その違いは、object 属性によって参照されるオブジェクトを (再帰的に) クローン作成する必要があるかどうかにあります。
私の写真を見せてください
#pos: 現在のオブジェクトのアドレス;
son: Son 属性が指すアドレス;
name : オブジェクトの属性の名前。
# (関連する推奨事項:Java 入門チュートリアル)
コードを見せてください#case1:public class Son implements Serializable , Cloneable{ private String name; private Son son; public Son() { super(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public Son getSon() { return son; } public void setSon(Son son) { this.son = son; } @Override public String toString() { return super.toString(); } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } }Test
public static void main(String[] args) throws Exception{ // 创建父亲(LiLiu),儿子(LiWu),孙子(LiLiu)并关联 Son father = new Son(); father.setName("LiSi"); Son son = new Son(); son.setName("LiWu"); Son grandSon = new Son(); grandSon.setName("LiLiu"); father.setSon(son); son.setSon(grandSon); // 调用clone方法 Son fatherCopy = (Son) father.clone(); boolean flag1 = fatherCopy==father; boolean flag2 = fatherCopy.getSon() == son; boolean flag3 = fatherCopy.getSon().getSon() == grandSon; // 比较克隆后的地址 System.out.println(flag1);// false System.out.println(flag2);// true System.out.println(flag3);// true // 比较Name flag1= fatherCopy.getName()==father.getName(); flag2 = fatherCopy.getSon().getName() == son.getName(); flag3 = fatherCopy.getSon().getSon().getName() == grandSon.getName(); System.out.println(flag1);// true System.out.println(flag2);// true System.out.println(flag3);// true //将对象写到流里 ByteArrayOutputStream byteOut=new ByteArrayOutputStream(); ObjectOutputStream objOut=new ObjectOutputStream(byteOut); objOut.writeObject(father); //从流里读出来 ByteArrayInputStream byteIn=new ByteArrayInputStream(byteOut.toByteArray()); ObjectInputStream objInput=new ObjectInputStream(byteIn); fatherCopy = (Son) objInput.readObject(); flag1= fatherCopy==father; flag2 = fatherCopy.getSon() == son; flag3 = fatherCopy.getSon().getSon() == grandSon; System.out.println(flag1);// false System.out.println(flag2);// false System.out.println(flag3);// false // 比较Name flag1= fatherCopy.getName()==father.getName(); flag2 = fatherCopy.getSon().getName() == son.getName(); flag3 = fatherCopy.getSon().getSon().getName() == grandSon.getName(); System.out.println(flag1);// false System.out.println(flag2);// false System.out.println(flag3);// false}上記のコードと実行結果から、オブジェクトが Cloneable を実装し、操作を実行せずに clone メソッドをオーバーライドする場合、 clone の呼び出しは浅いクローンであることが簡単にわかります。オブジェクト ストリームを使用してオブジェクトをストリームに書き込み、それを読み出すことは、ディープ クローン作成です。 考え方: Cloneable インターフェイスを実装してクローン インターフェイスを書き換えると、浅いクローン作成しか実行できなくなります。ただし、クラスの参照型属性 (および属性の参照型属性) が浅いクローンである場合は、参照型属性が存在しないか、参照型属性が null になるまで、全体として深いクローンが形成されます。オブジェクトの参照型属性と属性のアプリケーション型属性の両方が Coloneable を実装し、clone メソッドをオーバーライドして clone メソッド内で呼び出します。
protected Object clone() throws CloneNotSupportedException { Son result = (Son) super.clone(); if (son != null) { result.son = (Son) son.clone(); } return result; }個人的には、ディープ クローン作成方法を選択するときは、参照型属性に複数の階層の参照型属性関係があるかどうかなど、オブジェクトの複雑さに基づいて選択する必要があると思います。オブジェクトに参照タイプの属性のレイヤーが 1 つまたは 2 つしかない場合は、リフレクションで説明されている方法を選択する方が便利です。それ以外の場合は、オブジェクト フローを使用します。 関連する面接の質問については、次のサイトをご覧ください:
以上がJava のディープ クローン作成とシャロー クローン作成についての理解について話してください。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。