SlideShare a Scribd company logo
1 of 28
Effective Java 輪読会 第1回
(項目5~7)
2013/11/27
開発部 野口
項目5 不必要なオブジェクトの生
成を避ける
不変(immutable)オブジェク
ト
• 例1 : Stringクラス
{

String s1 = new String("stringette"); // この行の実行時にオ
ブジェクトが生成される
...

{
String s2 = new String("stringette"); // この行でも!
}
不変(immutable)オブジェク
ト
• 例1 : Stringクラスについては、こう書けば
よい
{
String s = "stringette“; // 同一仮想マシンで動作し、同じ文
字列リテラルを持っている他のコードでも同じオブジェクト
を再利用する
}
不変(immutable)オブジェク
ト
• 例2 : Booleanクラス
{
String booleanString = “true”;
Boolean b = Boolean(booleanString); // この行の実行時にオ
ブジェクトが生成される
}
不変(immutable)オブジェク
ト
• 例2 : Booleanクラスについては、こう書けばよい
{
String booleanString = “true”;
Boolean b = Boolean.valueOf(booleanString); //新たなオブ
ジェクトを生成しない
}
可変(mutable)オブジェクト
• 例 : pp.21 isBabyBoomer()メソッド
– boomStartとboomEndは何度呼ばれても変化すること
がない!にもかかわらず、呼ばれるたびに
• Calendar
• TimeZone
• Date * 2
のインスタンスを生成してしまう。
可変(mutable)オブジェクト
• 例 : pp.21 isBabyBoomer()メソッドでは、こう書けばよい
– static初期化子を使って、定数BOOM_STARTと
BOOM_ENDを一度だけ初期化する
可変(mutable)オブジェクト
• 注意 : 遅延初期化について
– でもisBabyBoomer()が呼ばれなかった時、
BOOM_STARTとBOOM_ENDの初期化が無駄になるので、
遅延初期化を行うのがベストなのでは……?
→実装が複雑になり、パフォーマンスにも大した改
善が見られないことが多いので、おすすめしない。
★パフォーマンス改善の第一原則 : 測れ
★時期尚早な最適化は諸悪の根源
Adapterパターン
• 例 : Map#KeySet
– Map#KeySet()はMapのキーの集合のビューを返すにす
ぎない。
– 何度呼ばれても、その都度インスタンスを生成しな
い。(同じインスタンスを返す)
– 疑問 : 「Adapterパターン」と書いた(書いてある)
が、「Map」は「Set」への「Adapter」なのか?とい
う点については、疑問。「Set」が「ビュー」という
ことなら納得できるが……。
→KeySetがSetへのアダプター
オートボクシング
• 例 : Long
public static void main(String[] args) {
Long sum = 0L;
for (long i = 0; i <= Integer.MAX_VALUE; i++) {
sum += 1; // ここでオートボクシングが行われる!
}
System.out.println(sum);
}

※Joshua Blockのマシン(スペック不明)では、43.2秒もか
かる!
(Longを使用しなければ、6.8秒)
注意
• 小さなオブジェクトを避けろというわけではな
い
– JVMが賢く振る舞ってくれたりする
– 明瞭性、簡潔性、能力(?)を向上するために必要
なら、それはよいこと
オブジェクトプール
• 「オブジェクトプール」はよくない
– コードが複雑になる
– そもそも、JVMのガーベッジコレクタに任せる方が性
能が高い可能性が高い
– たとえば、相当重く、コネクション数が限られてた
りするDBコネクション等は例外(プールする意味が
ある)
防御的コピー
• See also : 項目39 防御的コピー(必要な場合は、
オブジェクトを生成する)
項目6 廃れたオブジェクト参照を
取り除く
メモリリーク
• 例 : pp.24のStackクラス
– ここでリークする: return elements[--size];
– デクリメントする前の「size - 1」の要素には外部から
アクセスする手段がなくなるが、配列elementsはその

要素オブジェクトへの参照を保持している<廃れた
参照>
– 廃れた参照が参照しているオブジェクト……が参照し
ているオブジェクト……と言った具合に、多量のオブ
ジェクトがリークするおそれもある
メモリリーク
• 例 : pp.24のStackクラスへの解決策
– elements[size] = null; // 廃れた参照を取り除く
– もし間違ってその要素を参照した場合に、
NullPointerExeptionが発生することによって問題が早
期にわかるというメリットもある

– 注意:普通は、ローカル変数の適切な定義によって
参照が自然にスコープからはずれるようにすべき
メモリリーク
• リークしやすいとき
– クラスが独自のメモリを管理している時
– キャッシュ
– リスナーやコールバック
メモリリーク
• キャッシュの問題への対処
– WeakHashMapで実装する
– TimerやScheduledThreadPoolExecutorを用いる
– 新たなエントリーを追加する際の副作用として行う
メモリリーク
• リスナーやコールバックへの対処
– 弱い参照を用いる(例:WeakHashMap)
項目7 ファイナライザを避ける
ファイナライザは
C++のデストラクタとは違う
• デストラクタ:C++におけるリソース回収の一般
的な手段
– RAII(Resource Aquisition Is Initialization)
– Javaでデストラクタにあたるのは、ファイナライザで
はなくtry-finallyブロック
ファイナライザの欠点
• 即座にファイナライザが実行される保証がない
– ガーベッジコレクションの機能であり、JVMの実装に
依存する
– 低い優先順位で動作する「ファイナライザスレッ
ド」のために、ファイナライザを提供したことでオ
ブジェクトの回収が通常よりも遅れることさえある
– ファイナライザが実行される保証自体ない
• DBに対する永続性のあるロックをファイナライザ(だけ)で
解放すると、……(Coding Horror)

– System.gc、System.runFinalization、
System.runFinalizersOnExit、
Runtime.runFinalizersOnExit等々もいけてない
ファイナライザの欠点
• ファイナライザでスローされた例外がキャッチ
されなかった場合、ファイナライザが単に終了
する
• 深刻に遅い(実測値:ファイナライザがない場
合の約430倍)
かわりに明示的終了メソッド
を提供しよう
• 例 : InputStream、OutputStream、
java.sql.Connectionのcloseメソッド
– try-finallyで終了を保証する
ファイナライザが有効なとき
• 安全ネット
– その際は、エラーログを出すべき

• 重要な資源を保持していないネイティブピアの
回収
– 即座に開放すべき資源を保持しているなら、明示的
終了メソッドを持つべき
「ファイナライザ連鎖」は
自動的に実行されない
• サブクラスでfinalize()をオーバーライドしたら、
スーパークラスのファイナライザを明示的に呼
ぶ必要がある!
– ここでもtry-finallyを使用する

• ファイナライザガーディアンによって、finalize()
の呼び出しを保証できる
– 疑問:これならもはやfinalize()というメソッド名であ

る必要すらないのでは?
– 疑問:というか、finalize()というメソッド名にすると
必ず2回(以上)呼ばれてしまったりするのでは?
→そもそも、ファイナライザガーディアンを設定す
るときにはエンクロージングクラスにはfinalize()を設け
ない!
まとめ
• 安全ネットあるいは重要ではないネイティブ資
源を解放させること以外で、ファイナライザを
使用してはいけない
• super.finalizeを呼び出す
• 安全ネットとしての使用時には、エラーログを
出す
• ファイナライザガーディアンの使用を検討する

More Related Content

More from Appresso Engineering Team

マルチスレッド デザインパターン ― Single Threaded Execution
マルチスレッド デザインパターン ― Single Threaded Executionマルチスレッド デザインパターン ― Single Threaded Execution
マルチスレッド デザインパターン ― Single Threaded ExecutionAppresso Engineering Team
 
JavaScript 勉強会 ― 変数・演算子・文
JavaScript 勉強会 ― 変数・演算子・文JavaScript 勉強会 ― 変数・演算子・文
JavaScript 勉強会 ― 変数・演算子・文Appresso Engineering Team
 
Effective Java 輪読会 第7章 項目43-44
Effective Java 輪読会 第7章 項目43-44Effective Java 輪読会 第7章 項目43-44
Effective Java 輪読会 第7章 項目43-44Appresso Engineering Team
 
Effective Java 輪読会 第7章 項目41-42
Effective Java 輪読会 第7章 項目41-42Effective Java 輪読会 第7章 項目41-42
Effective Java 輪読会 第7章 項目41-42Appresso Engineering Team
 
Effective Java 輪読会 第7章 項目38-40
Effective Java 輪読会 第7章 項目38-40Effective Java 輪読会 第7章 項目38-40
Effective Java 輪読会 第7章 項目38-40Appresso Engineering Team
 

More from Appresso Engineering Team (20)

20150302 java8 第一回_ラムダ式(1)
20150302 java8 第一回_ラムダ式(1)20150302 java8 第一回_ラムダ式(1)
20150302 java8 第一回_ラムダ式(1)
 
Effective Java 輪読会 項目77-78
Effective Java 輪読会 項目77-78Effective Java 輪読会 項目77-78
Effective Java 輪読会 項目77-78
 
Effective Java 輪読会 項目74-75
Effective Java 輪読会 項目74-75Effective Java 輪読会 項目74-75
Effective Java 輪読会 項目74-75
 
マルチスレッド デザインパターン ― Single Threaded Execution
マルチスレッド デザインパターン ― Single Threaded Executionマルチスレッド デザインパターン ― Single Threaded Execution
マルチスレッド デザインパターン ― Single Threaded Execution
 
JavaScript 勉強会 ― 変数・演算子・文
JavaScript 勉強会 ― 変数・演算子・文JavaScript 勉強会 ― 変数・演算子・文
JavaScript 勉強会 ― 変数・演算子・文
 
JavaScript 勉強会 ― 型と値
JavaScript 勉強会 ― 型と値JavaScript 勉強会 ― 型と値
JavaScript 勉強会 ― 型と値
 
Effective Java 輪読会 項目69-70追加
Effective Java 輪読会 項目69-70追加Effective Java 輪読会 項目69-70追加
Effective Java 輪読会 項目69-70追加
 
Effective Java 輪読会 項目69-70
Effective Java 輪読会 項目69-70Effective Java 輪読会 項目69-70
Effective Java 輪読会 項目69-70
 
Effective Java 輪読会 項目66-68
Effective Java 輪読会 項目66-68Effective Java 輪読会 項目66-68
Effective Java 輪読会 項目66-68
 
Effective Java 輪読会 項目71-73
Effective Java 輪読会 項目71-73Effective Java 輪読会 項目71-73
Effective Java 輪読会 項目71-73
 
Java Day Tokyo 2014 まとめ (chen)
Java Day Tokyo 2014 まとめ (chen)Java Day Tokyo 2014 まとめ (chen)
Java Day Tokyo 2014 まとめ (chen)
 
Effective Java 輪読会 項目63-65
Effective Java 輪読会 項目63-65Effective Java 輪読会 項目63-65
Effective Java 輪読会 項目63-65
 
Effective Java 輪読会 項目60-62
Effective Java 輪読会 項目60-62Effective Java 輪読会 項目60-62
Effective Java 輪読会 項目60-62
 
Effective java 輪読会 項目57-59
Effective java 輪読会 項目57-59Effective java 輪読会 項目57-59
Effective java 輪読会 項目57-59
 
Effective Java 輪読会 項目49-52
Effective Java 輪読会 項目49-52Effective Java 輪読会 項目49-52
Effective Java 輪読会 項目49-52
 
Effective Java 輪読会 項目45-48
Effective Java 輪読会 項目45-48Effective Java 輪読会 項目45-48
Effective Java 輪読会 項目45-48
 
Effective Java 輪読会 項目53-56
Effective Java 輪読会 項目53-56Effective Java 輪読会 項目53-56
Effective Java 輪読会 項目53-56
 
Effective Java 輪読会 第7章 項目43-44
Effective Java 輪読会 第7章 項目43-44Effective Java 輪読会 第7章 項目43-44
Effective Java 輪読会 第7章 項目43-44
 
Effective Java 輪読会 第7章 項目41-42
Effective Java 輪読会 第7章 項目41-42Effective Java 輪読会 第7章 項目41-42
Effective Java 輪読会 第7章 項目41-42
 
Effective Java 輪読会 第7章 項目38-40
Effective Java 輪読会 第7章 項目38-40Effective Java 輪読会 第7章 項目38-40
Effective Java 輪読会 第7章 項目38-40
 

Effective java 輪読会 第2章 項目5,6,7