Java
 Computer >> コンピューター >  >> プログラミング >> Java

Javaのシャローコピーとディープコピーの違いを実例で徹底解説


シャローコピー(浅いコピー)とディープコピー(深いコピー)は、どちらも指定されたオブジェクトの複製を作成するための手法ですが、その仕組みと動作には重要な違いがあります。本記事では、それぞれの特徴をサンプルコードと実行結果をもとにわかりやすく解説します。

シャローコピー(浅いコピー)

シャローコピーでは、オブジェクトの新しいインスタンスを作成し、元のオブジェクトからデータをコピーします。ただし、配列などの参照型フィールドに関しては、データの実体ではなく「参照」だけが渡される点に注意が必要です。そのため、コピー元のデータを変更すると、コピー先のオブジェクトにも同じ変更が反映されてしまいます。この方式は「シャロークローニング」とも呼ばれ、新しく作成したインスタンスを扱う際には、元のオブジェクトの型へのキャストが必要になる場合があります。

コード例

import java.util.*;
class Demo{
    private int[] my_data;
    public Demo(int[] my_vals){
        my_data = my_vals; // 参照をそのまま代入(シャローコピー)
    }
    public void display_data(){
        System.out.println(Arrays.toString(my_data));
    }
}
public class Use_Demo{
    public static void main(String[] args){
        int[] my_vals = {56, 89, 91};
        Demo my_inst = new Demo(my_vals);
        my_inst.display_data();
        my_vals[0] = 65; // 元の配列を変更
        my_inst.display_data();
    }
}

実行結果

[56, 89, 91]
[65, 89, 91]

この例では、Demoクラスがint型の配列を受け取り、それをそのままフィールドへ代入しています。mainメソッドでインスタンスを生成し、display_dataメソッドで配列の中身を表示した後、元の配列my_valsの最初の要素を65に変更しています。すると、2回目の表示でもDemoインスタンス側の内容が[65, 89, 91]に変わっています。これは、コンストラクタが配列への参照をコピーしただけで、両者が同じデータを共有しているためです。

ディープコピー(深いコピー)

ディープコピーは、元のオブジェクトとは完全に独立したデータの複製が必要な場合に使用します。参照型のフィールドごとに新しいオブジェクト(配列など)を生成し、値を一つずつコピーする必要があります。Javaでは、Cloneableインターフェースを実装し、clone()メソッドをオーバーライドして独自のディープコピー処理を記述するのが一般的です。

コード例

import java.util.*;
class Demo{
    private int[] my_data;
    public Demo(int[] my_vals){
        my_data = new int[my_vals.length]; // 新しい配列を生成
        for (int i = 0; i < my_data.length; i++){
            my_data[i] = my_vals[i]; // 要素を一つずつコピー
        }
    }
    public void display_data(){
        System.out.println(Arrays.toString(my_data));
    }
}
public class Use_Demo{
    public static void main(String[] args){
        int[] my_vals = {56, 89, 91};
        Demo my_inst = new Demo(my_vals);
        my_inst.display_data();
        my_vals[0] = 65; // 元の配列を変更しても影響なし
        my_inst.display_data();
    }
}

実行結果

[56, 89, 91]
[56, 89, 91]

こちらの例では、コンストラクタ内で元の配列と同じ長さの新しい配列を生成し、forループを使って要素を一つずつコピーしています。そのため、mainメソッドで元の配列my_valsの値を変更しても、Demoインスタンス内のデータには一切影響しません。実行結果を見ると、2回目の表示でも元の値[56, 89, 91]が保たれていることが確認できます。

まとめ

シャローコピーは参照を共有するため軽量で高速ですが、コピー元とコピー先のデータが連動してしまうというデメリットがあります。一方、ディープコピーは完全に独立した複製を作成できる反面、その分だけメモリ消費や処理コストが増加します。パフォーマンスとデータの独立性のバランスを考慮し、用途に応じて適切なコピー方法を選択することが重要です。

  1. JavaでJTextAreaの切り取り・コピー・貼り付け機能を無効化する方法

    JTextAreaとは JTextAreaはJTextComponentクラスのサブクラスであり、テキストを表示したりユーザーのテキスト入力を受け付けたりするための複数行テキストコンポーネントです。JTextAreaの機能を実装する際には、キャレット(カーソル)の移動などを監視するCaretListenerインターフェースを利用できます。 デフォルトでは、JTextAreaクラスは切り取り(カット)、コピー、貼り付け(ペースト)の各機能を標準でサポートしています。しかし、アプリケーションの要件によっては、これらの操作を禁止したいケースもあります。そのような場合は、JTextAreaクラスのge

  2. JavaのJTextFieldで切り取り・コピー・貼り付け機能を実装する方法

    JTextFieldは、1行のテキストの編集を可能にするJTextComponentクラスのサブクラスです。JTextFieldコンポーネントに切り取り・コピー・貼り付けの機能を実装するには、cut()、copy()、paste()という各メソッドを使用します。これらはJTextComponentクラスにあらかじめ定義されているメソッドのため、追加の実装を行わなくてもすぐに呼び出して利用できます。 メソッドの構文 public void cut() public void copy() public void paste() 各メソッドの役割 cut():選択されているテキストをクリップボー