現在、javaによるプログラミングを行っています。
シャローコピーとディープコピーについてお聞きしたく質問させていただきます。
例えば、あるクラスDataをインスタンス化して、instance という名前のArrayListを作ったとします。
class Data{
int x;
int y;
int z;
}
それで、insというArrayListを別のData型のインスタンス化されたins2という型のArrayListにコピーしたいんですが。
現在は、 ins2.add(ins.get(~~));
といった感じで書いていて、処理の関係上途中、コピー元のinsをremove allで全部削除してしまっていたりしているんですが、ins2の中身は、insが削除されたにも関わらず何とも変化がなくて、一応目的の動きはしています。
シャローコピーの場合、参照元に何か変化があるとコピー先のものまで変化してしまうようなので、これは、ディープコピーということでいいんでしょうか?
A 回答 (4件)
- 最新から表示
- 回答順に表示
No.4
- 回答日時:
落ち着いて考えれば分かるはずです。
とりあえず言いたいことを整理させてもらいますが
・「ins」「ins2」はArrayList型の変数。
・「ins」にはData型のインスタンスを入れている。
・「ins2」に「ins」から取得したData型のインスタンスを入れた。
・「ins」の中身を消しているのに同じインスタンスを見ているはずの
「ins2」の中身は消えていない。⇒ナゼ??
ということで良いですか?
insのインスタンスが管理しているのは
「Data型のインスタンス」ではなく
「Data型のインスタンスへの参照情報」です。
早い話が、insはData型の参照変数を
配列形式に持っているだけです。
ins.get(~)によって返されるのも
「Data型のインスタンス」ではなく、
「Data型のインスタンスへの参照情報」です。
つまりins2が持っているのも
「Data型のインスタンスへの参照情報」です。
ここで、ins.removeAllとすると
消去されるのは「Data型のインスタンス(実体)」ではなく、
insの持つ「Data型のインスタンスへの参照情報」です。
「Data型のインスタンス(実体)」が消去されているわけではないので
ins2の持つ「Data型のインスタンスへの参照情報」はまだ有効なわけです。
すなわち、質問者様の状況はData型のインスタンスが
ディープコピーされているわけではないです。
そもそも、Javaというものは
開発者がインスタンスを直接消去したりすることはできません。
必ず、変数(参照情報)を介する仕組みになっており
インスタンスの消去はGCによってのみ行われます。
それさえ押さえていれば、今回のような質問には
いたらなかったのではないかなぁと思います。
No.3
- 回答日時:
こんにちは、kmeeさん、ディープコピーと言うのは
以下のような、結果のコードですかね???
class Data implements Cloneable{
int x,y;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class arraylist_clone {
public arraylist_clone() {
ArrayList<Data> ar1,ar2,ar3,ar4;
ar1= new ArrayList<Data>();
Data [] d = new Data[5];
for(int x=0;x<5;x++){
d[x]=new Data();
d[x].x=x+1;
d[x].y=x*10;
ar1.add(d[x]);
}
ar2=ar1;
ar3=(ArrayList<Data>) ar1.clone();
ar4=deepcopy(ar1);
System.out.println("元来");
show(ar1);
ar1.remove(4);
ar1.remove(2);
System.out.println("参照代入");
show(ar2);
System.out.println("シャローコピー");
show(ar3);
ar3.get(1).x=100;
ar3.get(1).y=200;
ar1.get(0).x=500;
ar1.get(0).y=600;
System.out.println("a1");
show(ar1);
System.out.println("a3");
show(ar3);
System.out.println("a4");
show(ar4);
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
new arraylist_clone();
// TODO code application logic here
}
private void show(ArrayList<Data> ar1) {
for(Iterator <Data> it=ar1.listIterator();it.hasNext();){
Data d = it.next();
System.out.println(d.x+" "+d.y);
}
}
private ArrayList<Data> deepcopy(ArrayList<Data> ar1) {
Data d = new Data();
ArrayList<Data> ad = new ArrayList<Data>();
for(Iterator<Data> it = ar1.iterator();it.hasNext();){
try {
ad.add((Data) it.next().clone());
} catch (CloneNotSupportedException ex) {
Logger.getLogger(arraylist_clone.class.getName()).log(Level.SEVERE, null, ex);
}
}
return ad;
}
}
実行結果
元来
1 0
2 10
3 20
4 30
5 40
参照代入
1 0
2 10
4 30
シャローコピー
1 0
2 10
3 20
4 30
5 40
a1
500 600
100 200
4 30
a3
500 600
100 200
3 20
4 30
5 40
a4
1 0
2 10
3 20
4 30
5 40
No.2
- 回答日時:
ins= →a0[ →d0, →d1,... ]
だとします。→a0はArrayListの、→d0,→d1はDataのインスタンスへの参照です。
シャローコピーしたins2は次のようになります
ins2= →a2[ →d0, →d1,... ]
つまり、中身がa0と同じ新しい ArrayListのインスタンスができます。
ここで、insを空にしても、影響するのはa0なので、a2には影響ありません。
参照元に変化、というのは、たとえば ins[0].x=0 などとして、dXに変更があった場合、同じインスタンスを参照しているins2も変化するということです。
(正確には,ins2自体は変化しないが、参照先が変化しているので、ins2[0].xなどとして取り出す値が変化する)
対して、 ディープコピーした ins3は次のようになります
ins3= →a3[ →d'0, →d'1,... ]
d'XはdXと中身は一緒ですが別のインスタンスです。dXに変更があっても、d'Xには影響ありません。
No.1
- 回答日時:
言葉の定義は、良く分からないので、
APIにある、シャローコピーと、代入のリストと結果を
載せてみました。
class Data{
int x,y;
}
public class arraylist_clone {
public arraylist_clone() {
ArrayList<Data> ar1,ar2,ar3;
ar1= new ArrayList<Data>();
Data [] d = new Data[10];
for(int x=0;x<10;x++){
d[x]=new Data();
d[x].x=x+1;
d[x].y=x*10;
ar1.add(d[x]);
}
ar2=ar1;
ar3=(ArrayList<Data>) ar1.clone();
System.out.println("元来");
show(ar1);
ar1.remove(5);
ar1.remove(2);
System.out.println("参照代入");
show(ar2);
System.out.println("シャローコピー");
show(ar3);
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
new arraylist_clone();
// TODO code application logic here
}
private void show(ArrayList<Data> ar1) {
for(Iterator <Data> it=ar1.listIterator();it.hasNext();){
Data d = it.next();
System.out.println(d.x+" "+d.y);
}
}
}
結果
元来
1 0
2 10
3 20
4 30
5 40
6 50
7 60
8 70
9 80
10 90
参照代入
1 0
2 10
4 30
5 40
7 60
8 70
9 80
10 90
シャローコピー
1 0
2 10
3 20
4 30
5 40
6 50
7 60
8 70
9 80
10 90
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# 【C++】IDirect3DSurfaceのディープコピーは可能ですか? 1 2022/07/06 02:47
- Java Java です 途中は省いてますが for(int i = 0; i < 25; i ++) { s 4 2022/05/20 23:36
- C言語・C++・C# 関数ポインタの高速化のメリット 7 2023/05/05 20:15
- Java JavaのSingletonパターンのprivateの持つ意味が分かりません。 5 2022/06/12 10:38
- C言語・C++・C# pythonのファイルの並びでの読み込みとリストについて 4 2022/04/13 03:52
- C言語・C++・C# 10個の実数に対する降順ソート結果を出力するプログラムを作りたいのですが、以下のプログラムをどう直せ 1 2022/07/09 22:16
- C言語・C++・C# c言語の問題です 課題1 (二分探索木とセット) 大きさ size の配列 array を考える。す 2 2023/01/10 21:08
- Illustrator(イラストレーター) Illustrator アンカーポイント選択について 3 2023/01/30 12:31
- Excel(エクセル) 複数セルデータを別シートの単一セルにコピーしたい。(詳細をご参照ください) 1 2022/12/14 15:08
- C言語・C++・C# c言語でユーザ関数を利用して入力された文字列を反転させるプログラムを作りたいです。 3 2023/01/29 19:47
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
変数名の付け方
-
C#において、同じインスタンス...
-
インスタンス参照でアクセスで...
-
複数の変数を宣言する時、同時...
-
private static という変数の修飾
-
C# インスタンスの破棄
-
VB.NET getとsetの概念がわかり...
-
javaのクラスの作り方、エラー...
-
newしないインスタンス?実体化...
-
SQLを連続発行する時の正しい(?...
-
文字列を日付に変換でParseExce...
-
ASPX(C#)で別ファイルで自分で...
-
String a = "a"; と String b =...
-
変数の参照でエラーが出てしま...
-
フォームの存在をチェックする方法
-
SetWindowsHookExで質問
-
C#の構造体の開放のしかた
-
生成したインスタンスを削除す...
-
擬似コード
-
インスタンスのハンドル
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
変数名の付け方
-
インスタンス参照でアクセスで...
-
private static という変数の修飾
-
複数の変数を宣言する時、同時...
-
VB.NET getとsetの概念がわかり...
-
C#において、同じインスタンス...
-
生成したインスタンスを削除す...
-
SQLを連続発行する時の正しい(?...
-
C# インスタンスの破棄
-
「インスタンス」の意味をわか...
-
変数の参照でエラーが出てしま...
-
newしないインスタンス?実体化...
-
オブジェクト参照がオブジェク...
-
String a = "a"; と String b =...
-
文字列を日付に変換でParseExce...
-
エクセル(複数インスタンス)...
-
フォームの存在をチェックする方法
-
C#の構造体の開放のしかた
-
マルチスレッド間でデータ交換...
-
vb.netでFAXを送信する方法
おすすめ情報