Javaのメソッドでリストのコピーを返すべき理由とカプセル化の概念

こんにちは。ゆうせいです。

新人研修中に受講者から以下の質問をいただきました。

Javaのメソッドでリストのコピーを返す理由は?

今回はこの質問に答えたいと思います。

Javaでプログラムを記述する際、クラスの内部で保持しているリストを外部に公開することがあります。このとき、リストそのものを渡すのではなく、リストの複製(コピー)を作成して返す手法が推奨されます。この手法は防御的コピーと呼ばれ、プログラムの安全性と信頼性を高めるために不可欠な知識です。

参照渡しによる意図しない書き換えの防止

Javaにおけるリストはオブジェクトであり、変数にはオブジェクトの実体ではなく、その所在を示す参照情報が格納されています。

参照という仕組みの解説

参照とは、ホテルの部屋番号のようなものです。メソッドがリストそのものを返すと、呼び出し元に部屋番号を教えることになります。部屋番号を知っている人は誰でも、部屋の中にある家具(リストの要素)を勝手に並べ替えたり、持ち出したりできてしまいます。

もしコピーを返さずにリストを共有した場合、外部のプログラムがリストの内容を変更すると、クラス内部のデータも書き換わってしまいます。これは、クラスが自分自身のデータを管理できていない状態を意味します。

カプセル化の維持

カプセル化とは、オブジェクトの内部状態を外部から保護し、決められた窓口(メソッド)を通してのみ操作を許可する設計指針です。

高校の部活動の名簿を例に挙げます。名簿の原本をそのまま部外者に貸し出してしまうと、勝手に名前を消されたり書き加えられたりする恐れがあります。これを防ぐために、原本は部室に保管したまま、コピーを取って渡すのがカプセル化の考え方です。

コードによる具体例の比較

以下のコードは、リストをそのまま返す場合と、コピーを返す場合の挙動の違いを示しています。

修正前のコード(リスクがある状態)

この構成では、外部からリストの中身を自由に削除できてしまいます。

public class StudentGroup {
    private List<String> names = new ArrayList<>();
    public StudentGroup() {
        names.add("田中");
        names.add("佐藤");
    }
    public List<String> getNames() {
        return names;
    }
}

修正後のコード(安全な状態)

新しいリストのインスタンスを作成して返すことで、外部からの変更が内部に影響しないようにします。

public class StudentGroup {
    private List<String> names = new ArrayList<>();
    public StudentGroup() {
        names.add("田中");
        names.add("佐藤");
    }

    public List<String> getNames() {
        return new ArrayList<>(names);
    }
}

メリットとデメリット

リストのコピーを返す手法には、確実なメリットがある一方で、計算資源の消費という側面も存在します。

項目内容
メリット:データの安全性外部の操作によってクラス内部の状態が壊されるリスクを排除できる。
メリット:バグの抑制どこでデータが書き換わったか分からなくなる追跡不能なエラーを防止できる。
デメリット:メモリ消費リストの要素数が多い場合、コピーを作成するたびに新しいメモリ領域を消費する。
デメリット:処理速度要素をすべてコピーするため、非常に巨大なリストでは処理時間が無視できない場合がある。

学習のステップ

リストのコピーを適切に扱えるようになるために、以下の順序で学習を進めてください。

  1. 参照型と基本型の違いの理解:Javaにおけるオブジェクトの扱われ方を、変数のメモリイメージと共に学習します。
  2. インスタンス化の仕組み:new演算子が何を行っているのかを理解し、同じ内容を持つ別々のオブジェクトという概念を把握します。
  3. 防御的コピーの実装:ArrayListのコンストラクタに別のリストを渡す方法など、具体的なコピーの記述方法を練習します。
  4. 不変(イミュータブル)なコレクション:コピーを返す以外の手法として、中身を変更できないリストを返す方法(Collections.unmodifiableListなど)についても学習を広げます。

これらの段階を踏むことで、外部からの干渉を受けない、堅牢なクラス設計ができるようになります。

グループでは新人エンジニア研修のアシスタント講師を募集しています。

投稿者プロフィール

山崎講師
山崎講師代表取締役
セイ・コンサルティング・グループ株式会社代表取締役。
岐阜県出身。
2000年創業、2004年会社設立。
IT企業向け人材育成研修歴業界歴20年以上。
すべての無駄を省いた費用対効果の高い「筋肉質」な研修を提供します!
この記事に間違い等ありましたらぜひお知らせください。

学生時代は趣味と実益を兼ねてリゾートバイトにいそしむ。長野県白馬村に始まり、志賀高原でのスキーインストラクター、沖縄石垣島、北海道トマム。高じてオーストラリアのゴールドコーストでツアーガイドなど。現在は野菜作りにはまっている。