読者です 読者をやめる 読者になる 読者になる

Effective Java 第 2 版:第 2 章 オブジェクトの生成と消滅 項目 5

不必要なオブジェクトの生成を避ける

リソースを効率よく使うためには、以下のような不必要なオブジェクトの生成はできるだけ避けたいという話。

  • 不変クラスを毎回 new
  • メソッドが呼び出されるごとの高コストなオブジェクトの生成
  • アダプターの複数個生成
  • 意図しないオートボクシング

不変クラスを毎回 new

不変クラスの例として String で考えるとわかりやすい。 String str = new String("Hogeeee"); は、ループ内などで何度も実行されると、その回数分だけインスタンスを生成してしまう。 その代わりに、String str = "Hogeeee"; のように文字列リテラルを使えば、何度実行しても 1 個のインスタンスを共有できる。

また、static ファクトリーは不必要なインスタンスを生成しないことがほとんど。

メソッドが呼び出されるごとの高コストなオブジェクトの生成

メソッドの中に生成コストの大きいインスタンス(例として Calender, TimeZone が挙げられている)を生成する処理があると、 そのメソッドが呼び出されるたびにインスタンスの生成が起き、コストがかかる。 その代わりに、以下のように static 初期化子を使って、クラス初期化時点でインスタンスを生成するようにしておくとよい。

public class Hoge {
    static {
        // クラスのインスタンス生成時に一度だけ初期化される
        Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("JST"));
        // ...その他の重い初期化
    }

    public void doSomething() {
        // ...
    }
}

アダプターの複数個生成

Map#keySet で返される Set ビューは Map の内部に対するインタフェースの役割を果たし、処理は内部へ委譲しているアダプターといえる。 この場合、一つの Set ビューから内部を変更すると、他の Set ビューから見てもその変更が反映されている。 つまり、どのインスタンスから内部を見ても同じ状態であるため、複数インスタンスを生成する必要はない。

意図しないオートボクシング

オートボクシングとは、基本データ型から基本データ型のラッパークラスに自動で変換される Java の機能である。 例えば、以下のコードでは int 型の値が Integer クラスのオブジェクトに自動で変換される。

Integer i = 10;

これは便利な機能ではあるが、何度も実行されたとき、コストが大きくなってしまう。 そのため、不必要な場面でオートボクシングが起きないように気を付ける必要がある。

参考文献

EFFECTIVE JAVA 第2版 (The Java Series)

EFFECTIVE JAVA 第2版 (The Java Series)