読書:Java本格入門

Java本格入門|Amazon
Java本格入門|技術評論社

少し前に話題になったJava本。「Javaを使ってきたけど、最新のJavaのトレンドを抑えたい」という気持ちで購入した。非常に役に立つ本だった。

コレクションの使い方から、マルチスレッド時の注意事項、Apache Commonsなどのライブラリの事まで、幅広く記載されている。幅広いけど実戦で使える内容に絞られている。短時間で役に立つ知識が身につけられる一冊。

自分の知識が増えたと思う内容をまとめておく。

プリミティブ型

プリミティブ型からラッパークラスに変換するときは、valueOfメソッドを使う。-127から128の範囲であれば、事前にオブジェクトが生成済みで、新規にオブジェクトを生成することがなく効率的。

いつも、IntegerとintとStringの変換メソッドが思い出せないので、以下にまとめておく。

// StringとIntegerの変換
Integer num = Integer.valueOf("1");
String str = num.toString();

// Integerとintの変換
Integer num = Integer.valueOf(2);
int i = num.intValue();

// intとStringの変換
int i = Integer.parseInt("3");
String str = String.valueOf(i)

配列の初期化

配列の初期化方法は3パターン。

// 宣言時に内容が決まっていないとき
int[] array1 = new int[ 10];
// 宣言時時に内容が決まっているとき
int[] array2 = { 1, 2, 3, 4, 5 };
// 宣言時時に内容が決まっているとき
int[] array3 = new int[] { 10, 9, 8, 7, 6 };

配列のコピーには、Arrays.copyOfメソッドが使える。

コレクション

コレクションクラスのところでは、使い所がまとめられている。まとめがあると分かりやすいし、なぜこういう使い分けをするべきかも書かれている。

・配列の途中で要素の追加や削除をおこなうことが多い
→ LinkedList
・for文などを使った全体的な繰り返し処理が多い
→ ArrayList
・複数スレッドから同時にアクセスする
→ CopyOnWriteArrayList

・キーの大小を意識した部分集合を取り扱う場合
→ TreeMap
・要素の順序を保持する必要がある場合
→ LinkedHashMap
・複数スレッドから同時にアクセスする場合
→ ConcurrentHashMap
・その他の場合
→ HashMap

マルチスレッド

マルチスレッドのところでは、以下のような注意事項があったり・・。どう対応するのかも書かれている。

HashMapに対して複数のスレッドから同時にアクセスする場合は、次のような対処が必要になります。
・複数のスレッドから同時にアクセスできないように、synchronizedなどにより同期化する
・複数のスレッドからアクセスされても安全に使えるConcurrentHashMapを使用する

ユーティリティクラス

ユーティリティクラスはstaticメソッドにしない。利用する側のクラスに、staticインスタンスで持たせる方法があるという話し。テストの時にモック化できない問題は分かるけど、利用側クラスでstaticインスタンスにしてくれるか心配。自分はIoCコンテナに登録している。

全てのメソッドをstaticとする、ユーティリティクラスを作成することがよくあります。ユーティリティクラスのメソッドがすべてstaticである理由は、インスタンス生成の無駄を省くことにあります。ユーティリティクラスを毎回newしてメソッドを呼び出すよりも、直接メソッドを呼び出したほうが効率的だからです。

ただし、staticメソッドばかりでは拡張性がなく、またテストをおこなう際にメソッドをモック化できないため、筆者は普段、ユーティリティクラス自体は非staticメソッドで構成して、インスタンスをstaticにする手法を採用しています。

ログ出力

ログの出力のところでは、このような問題があることが記載されている。

その際、次に示すように記述してしまうと、パフォーマンスが悪くなってしまう可能性があります。
logger.debug(“employee=”+employee+“,department=”+department);

アプリケーションのログレベルがINFOで動作していた場合、DEBUGレベルのログは出力されません。しかし、その出力レベルの判定は、ライブラリの中でおこなわれます。上記のコードでは、ライブラリの中に入る前に、employeeオブジェクトとdepartmentオブジェクトのtoStringメソッドを実行することになり、toStringメソッドの処理が重いために、アプリケーションのパフォーマンスも悪くなってしまいます。

これは、少し前に仕事で問題となったところだった。SL4Jではこの問題は解決されていて、プレースホルダーを利用することで、ライブラリ内でtoStringメソッドが実行されるようになっているとのこと。つまり、INFOで動作しているときはdebugメソッド内のtoStringメソッドは呼ばれずに、パフォーマンスが悪くなることがない。