LoginSignup
0
0

More than 3 years have passed since last update.

Effective Java(第3版) 項目6 不必要なオブジェクトの生成を避ける

Last updated at Posted at 2021-05-03

可能であれば、新しいオブジェクトを生成せずに、再利用したほうが良い、という内容です。

記載内容

不変なオブジェクトの再利用

オブジェクトが不変であれば、常に再利用できる。

極端な例として、以下の様なインスタンス生成は意味がない。

String s = new String("foobar");

ファクトリメソッド

コンストラクタを使用すると、(言語仕様のために)新しいオブジェクト生成が必須になるが、
ファクトリメソッドはオブジェクト生成を避けられる可能性がある。
例として、基本データ型のラッパークラスは、常にファクトリメソッドを使用することで、
不要なインスタンス生成を避けられる可能性がある。

インスタンス生成が高負荷なオブジェクト

正規表現のコンパイル結果であるPatternインスタンス等、生成が高価なインスタンスを繰り返し生成するのを避ける必要がある。
そのため、繰り返し使用する正規表現に対して、String.matchesを使用するべきではない。

アダプター

アダプターは、あるオブジェクトが保持しているデータへアクセスするための、代替のインタフェースを提供するパターン。
あるオブジェクトに対するアダプターは、1つのインスタンスを再利用できる。
例として、MapインタフェースのkeySetメソッドは、Setを返してはいるが、毎回同じインスタンスを返しても問題ない。
それらのSetは同じMapに紐づいており、Mapの更新がすべてのSetに反映される。
このSetのインスタンスが複数あっても無意味なので、1つのインスタンスを再利用したほうが良い。

ボクシング

自動ボクシングは、基本データ型とラッパークラスを区別せずにプログラミングできるように見せかけているが、
見せかけであり、ラッパークラスのインスタンス生成により、パフォーマンスに影響する場合がある。
そのため、意図しない自動ボクシングに注意する必要が有る。

防御的コピー

防御的コピーが必要なケースでは、既存のオブジェクトを再利用してはならない。
防御コピーが必要なケースで、オブジェクトを再利用したい場合のペナルティは、
不必要なインスタンス生成によるペナルティよりもはるかに重大な影響を及ぼすことがある。

考察

不必要なオブジェクト生成を避けるのは当然なのですが、
実際には考えるべき内容が多い項目と思います。

コンストラクタとファクトリメソッド

自分でクラスを作る場合、何も考えなければコンストラクタを提供しますが、
不変クラスを作る場合、ファクトリメソッドの提供を考えるべきと思います。
実装当初は単に内部でコンストラクタを呼んでreturnするだけかも知れませんが、
将来的にキャッシュ等でインスタンス生成を削減できる可能性があるためです。

ただ、どのクラスでもファクトリメソッドを提供するとなると、実装の手間が増えますし、
使用する側もインスタンス生成方法が分かりづらいというデメリットがあります。
そのトレードオフを考え、ファクトリメソッドを提供するべきかを考える必要が有りそうです。

ただ、一度コンストラクタを提供してしまうと、既存コードを修正しないと、
ファクトリメソッドの使用を強制できないのが難点です。

ライブラリ内でのインスタンス生成が高負荷なオブジェクトの生成

インスタンス生成が高負荷なオブジェクトの生成は避けたいのですが、
知らずにライブラリ内で高負荷なインスタンス生成を行ってしまう可能性があります。
標準ライブラリであれば、JavaDocの記載を確認することで避けることが出来ますが、
JavaDocが不十分なライブラリ(もしくは他のプログラマが作成したクラス)を使用している場合、
避けるのが難しいケースが有りそうです。

また、逆のパターンとして、同じ区切り文字(1文字)で、String.splitを繰り返し使用する場合、
Patternインスタンスを生成、再利用すると、逆に遅くなります。
これは、String.split内で、1文字の区切り文字に対する最適化が行われており、
Patternを使用せずに実装されているためです。
(JavaDocに記載は無いですが、適切な最適化だと思います)

そのレベルで自分が使用するクラスを認識するのは、コストもかかりますので、
全てのクラスを知り尽くす、というわけにもいきません。
十分なJavaDocが記載されていれば良いですが、全てのクラス(そして全てのプログラマ)に
それを求めるのも難しいというのが実情と思います。

最終的には、性能測定で問題がある場合、プロファイリング等で不要なインスタンス生成を確認し、
修正を行っていく、という対症療法的な手法になってしまいそうです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0