ホームページ >Java >&#&面接の質問 >Java のディープ クローン作成とシャロー クローン作成についての理解について話してください。

Java のディープ クローン作成とシャロー クローン作成についての理解について話してください。

王林
王林転載
2021-01-30 09:53:352242ブラウズ

Java のディープ クローン作成とシャロー クローン作成についての理解について話してください。

Alibaba の面接官の質問:

Java のディープ クローン作成とシャロー クローン作成についての理解を話してください

回答:

(注: この記事は、ディープ クローニングとシャロー クローニングの違いと実装方法について説明しています?)

話は安いです

#私はこれまでに、ディープ クローニングとシャロー クローニング (ディープ コピー、シャロー コピー) に遭遇したことがあります。最近一度質問したのですが、クローン方法があるという印象以外、混乱しています! ! !クローン作成 (コピー) は、オブジェクトのコピーを迅速に取得する Java の一般的な操作です。クローン作成はディープ クローン作成とシャロー クローン作成に分けられます。

浅いクローン: 新しいオブジェクトを作成します。新しいオブジェクトのプロパティは、元のオブジェクトとまったく同じです。非基本型プロパティの場合、それらは依然として、ポイントされているオブジェクトのメモリ アドレスを指します。元のプロパティによる。

ディープ クローン作成: 新しいオブジェクトを作成すると、属性で参照されている他のオブジェクトもクローン化され、元のオブジェクト アドレスを指さなくなります。

つまり、ディープ クローン作成とシャロー クローン作成はどちらもヒープ内に新しい領域を割り当てますが、その違いは、object 属性によって参照されるオブジェクトを (再帰的に) クローン作成する必要があるかどうかにあります。

私の写真を見せてください

#pos: 現在のオブジェクトのアドレス;

son: Son 属性が指すアドレス;

name : オブジェクトの属性の名前。

Java のディープ クローン作成とシャロー クローン作成についての理解について話してください。

# (関連する推奨事項:

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 面接の質問と回答

以上がJava のディープ クローン作成とシャロー クローン作成についての理解について話してください。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はcnblogs.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。