Tbpgr Blog

Employee Experience Engineer tbpgr(てぃーびー) のブログ

書籍 Effective Java | 必要な場合には、防衛的にコピーする

パンくず

Effective Java
必要な場合には、防衛的にコピーする

概要

必要な場合には、防衛的にコピーする

詳細

クラスの内部を変更されたくない場合は、防衛的コピーによって
参照を渡さずに値をコピーして渡すこと。
これにより、外部から意図せぬ変更をされることを防ぎます。
また、クラス内から外部に値を返却する際も
防衛的コピーを行った値を返却すること。

上記は副作用の無いクラスを作成する上で重要な要素であるが
コピーのコストが大きい場合は、クラスの利用者が信頼出来る相手に限られている場合は
ドキュメンテーションを残した上で防衛的コピーを行わないという判断も可能。

サンプルコード

package effective.creation.chapter6;

public class SampleNo39 {
  public static class InnerHoge {
    private String name;
    private int age;

    public InnerHoge name(String name) {
      this.name = name;
      return this;
    }

    public InnerHoge age(int age) {
      this.age = age;
      return this;
    }

    public String getName() {
      return name;
    }

    public int getAge() {
      return age;
    }

    @Override
    public String toString() {
      return "InnerHoge [name=" + name + ", age=" + age + "]";
    }
  }

  public static class HogeBefore {
    private final InnerHoge hoge;

    public HogeBefore(InnerHoge hoge) {
      this.hoge = hoge;
    }

    public InnerHoge hoge() {
      return hoge;
    }

    @Override
    public String toString() {
      return "HogeBefore [hoge=" + hoge + "]";
    }
  }

  public static class HogeAfter {
    private final InnerHoge hoge;

    public HogeAfter(InnerHoge hoge) {
      this.hoge = new InnerHoge().name(hoge.name).age(hoge.age);
    }

    public InnerHoge hoge() {
      return new InnerHoge().name(hoge.name).age(hoge.age);
    }

    @Override
    public String toString() {
      return "HogeBefore [hoge=" + hoge + "]";
    }
  }

  public static void main(String[] args) {
    InnerHoge hoge = new InnerHoge().name("hoge").age(20);
    HogeBefore hogeBefore = new HogeBefore(hoge);
    HogeAfter hogeAfter = new HogeAfter(hoge);

    hoge.name("hage");
    hoge.age(30);
    System.out.println(hogeBefore);
    System.out.println(hogeAfter);

    hogeBefore.hoge().name("hige");
    hogeAfter.hoge().name("hige");

    System.out.println(hogeBefore);
    System.out.println(hogeAfter);

  }
}