JAvaにおけるcloneの学習
5361 ワード
今日はeffective javaの中のcloneの使用を見て、それについて少し理解して、以下は自分の理解したことを書いて、後で運用するために~~~~
JAvaでオブジェクトのコピーを実装するには、Objectのclone()メソッド、自分の書いたクラスに対してcloneableインタフェースを実装し、親クラスのclone()メソッドを上書きすることができます.
従来のオブジェクトには次のような値が割り当てられています.
上のt 2=t 1は、t 1とt 2を同時に同じメモリに向けただけで、t 2の変更にもt 1に影響しますが、t 2の変更がt 1に影響しないとしたらどうすればいいのでしょうか.
実はとても简単で、これはObject类のclone()方法を使うことができて、同时にCloneableインタフェースの改善したコードを実现して、以下の通りです:
このようにt 2は新しいオブジェクト参照であり、Test t 2=new Test(「www」)と同様に、t 1とt 2は異なるメモリ空間を指し、t 2の設定値はt 1に影響しない.
しかし、このようにするともう一つの問題が発生します.次のコードを見てください.
上のt 1の出力はnullではなく4444であることがわかりますが、これはなぜでしょうか??
実はObjectクラスのclone()メソッドは、上のプログラムのように、t 1とt 2のmapメンバー変数が指すメモリアドレスが同じであるため、いずれかの内部要素の値が同じオブジェクトをコピーすることで、同じメモリ空間を指さないようにすることができますが、mapのキー値を変更すると、彼ら2人は同時に同じ空間を指しており、1つは変化し、もう1つは変化します.
解決策は次のとおりです.
clone()メソッドを書き換え、メンバー変数もclone()1部にすることで、上記の問題を解決することができ、オブジェクト配列もこのように処理されます.実際には、あなたが使用しているオブジェクトのclone()メソッドであれば、clone()メソッドを書き換えることが望ましいです.
まあ、なんとか書き終わったけど、JDKの中のcloneという方法にはいろいろ問題があったので、たくさんの牛たちはお勧めしないので、基本的な問題は後でゆっくり発掘しておきました~~~
JAvaでオブジェクトのコピーを実装するには、Objectのclone()メソッド、自分の書いたクラスに対してcloneableインタフェースを実装し、親クラスのclone()メソッドを上書きすることができます.
従来のオブジェクトには次のような値が割り当てられています.
public class Test{
private String str;
public Test(String str){
this.str = str;
}
public void setStr(String str){
this.str = str;
}
public String getStr(){
return this.str;
}
public static void main(String args[]){
Test t1 = new Test("www");
Test t2 = t1;
t2.setStr("ddd");
System.out.println(t1.getStr());// ddd
System.out.println(t2.getStr());// ddd
}
}
上のt 2=t 1は、t 1とt 2を同時に同じメモリに向けただけで、t 2の変更にもt 1に影響しますが、t 2の変更がt 1に影響しないとしたらどうすればいいのでしょうか.
実はとても简単で、これはObject类のclone()方法を使うことができて、同时にCloneableインタフェースの改善したコードを実现して、以下の通りです:
public class Test implements Cloneable{
private String str;
public Test(String str){
this.str = str;
}
public void setStr(String str){
this.str = str;
}
public String getStr(){
return this.str;
}
public static void main(String args[]) throws CloneNotSupportedException{
Test t1 = new Test("www");
Test t2 = (Test) t1.clone();
t2.setStr("ddd");
System.out.println(t1.getStr());// www
System.out.println(t2.getStr());// ddd
}
}
このようにt 2は新しいオブジェクト参照であり、Test t 2=new Test(「www」)と同様に、t 1とt 2は異なるメモリ空間を指し、t 2の設定値はt 1に影響しない.
しかし、このようにするともう一つの問題が発生します.次のコードを見てください.
public class Test implements Cloneable{
private String str;
private HashMap<Integer, String> map = new HashMap<Integer, String>();
public Test(String str){
this.str = str;
map.put(1, "1111");
map.put(2, "2222");
map.put(3, "3333");
}
public void setStr(String str){
this.str = str;
}
public String getStr(){
return this.str;
}
public HashMap<Integer, String> getMap(){
return this.map;
}
public static void main(String args[]) throws CloneNotSupportedException{
Test t1 = new Test("www");
Test t2 = (Test) t1.clone();
t2.setStr("ddd");
System.out.println(t1.getStr());// www
System.out.println(t2.getStr());// ddd
t2.getMap().put(4, "4444");
System.out.println(t1.getMap().get(4));// 4444( null)
System.out.println(t2.getMap().get(4));// 4444
}
}
上のt 1の出力はnullではなく4444であることがわかりますが、これはなぜでしょうか??
実はObjectクラスのclone()メソッドは、上のプログラムのように、t 1とt 2のmapメンバー変数が指すメモリアドレスが同じであるため、いずれかの内部要素の値が同じオブジェクトをコピーすることで、同じメモリ空間を指さないようにすることができますが、mapのキー値を変更すると、彼ら2人は同時に同じ空間を指しており、1つは変化し、もう1つは変化します.
解決策は次のとおりです.
public class Test implements Cloneable{
private String str;
private HashMap<Integer, String> map = new HashMap<Integer, String>();
public Test(String str){
this.str = str;
map.put(1, "1111");
map.put(2, "2222");
map.put(3, "3333");
}
public void setStr(String str){
this.str = str;
}
public String getStr(){
return this.str;
}
public HashMap<Integer, String> getMap(){
return this.map;
}
public static void main(String args[]) throws CloneNotSupportedException{
Test t1 = new Test("www");
Test t2 = (Test) t1.clone();
t2.setStr("ddd");
System.out.println(t1.getStr());// www
System.out.println(t2.getStr());// ddd
t2.getMap().put(4, "4444");
System.out.println(t1.getMap().get(4));// null
System.out.println(t2.getMap().get(4));// 4444
}
@Override public Test clone(){
Test obj = null;
try {
obj = (Test) super.clone();
obj.map = (HashMap<Integer, String>) obj.map.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return obj;
}
}
clone()メソッドを書き換え、メンバー変数もclone()1部にすることで、上記の問題を解決することができ、オブジェクト配列もこのように処理されます.実際には、あなたが使用しているオブジェクトのclone()メソッドであれば、clone()メソッドを書き換えることが望ましいです.
@Override public Test clone(){
Test obj = null;
try {
obj = (Test) super.clone();
//clone
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return obj;
}
まあ、なんとか書き終わったけど、JDKの中のcloneという方法にはいろいろ問題があったので、たくさんの牛たちはお勧めしないので、基本的な問題は後でゆっくり発掘しておきました~~~