はじめに
この度、11月某日にJava SE 8 Programmer II(Gold)を受験し、無事合格致しました。
様々な合格体験記がこのQiitaにはございますし、私自身、Gold受験を思い立ったのが5月ごろということでお世辞にも効率よい勉強の仕方が出来たとは思いません。
しかし、時間をかけた分操作のプロセス、思想などを深く掘り下げて理解することが出来たと感じています。実際満点とはいきませんでしたが、問題に対してプロセスを追い、噛み砕きながら解いていくことが出来ました。
資格を取るにあたり、ただ問題集を闇雲に頼らず、己の知識として吸収することが出来たのは良い経験になりました。
本記事では、頻出とかは関係なく面白いと思った内容を辿っていこうと思います。
Stream Pipeline
Goldを受験する際避けて通れないStream APIですが、操作の流れが一見誤解されそうな仕組みをとっています。しかし、一度理解すればStream関連の問題にしっかり活きてくる内容だと思います。
以下に例を示します。
public class example{
public static void main(String[] args){
Stream<String> fruit = Stream.of("banana", "grape", "orange","apple");
.filter(s -> s.length() > 5)
.peek(System.out::print)
.map(String::toUpperCase)
.peek(System.out::print);
long l = fruit.count();
}
}
終端操作countが示されているため、fruitで定義された中間操作が遅延して実行されます。では、Streamの各要素はどのように処理されていくのでしょうか。
私は、学習初期では以下のような流れを想像していました。
即ち、一つの中間操作ごとにすべての要素が検証されると思っていました。これが正しければ、出力はbananaorangeBANANAORANGE
になるはずです。一見正しいように思えます。
しかし、実際は異なり、Stream.ofで定義された要素が一つずつ最後まで操作されてから次の要素に移る、という流れでした。
つまり、peekの実行順序は②→④→⑦→⑨となるため、出力はbananaBANANAorangeORANGE
です。
実際にStreamを使う場合意識する必要は無いかもしれませんが、操作順序の流れは一度理解してしまえば見た目が多少変わっても動じずに紐解くことが出来ます。なお、終端操作countが無かった場合、Streamが中間操作のみの為何も出力されない点にも注意が必要です。終端操作が正しく記載されているかもよく問われます。(Optional絡みが特に多かった気がします)
muiti-catchとtry-with-resource
例外とアサーションの分野で数問出題されますが、他の項目より容易に覚えやすいので取りこぼしたくないところです。実務でも避けて通れないところ(だと思う)なので習得が確実に活きる分野だと思います。
まずSE7で導入されたmulti-catch。こちらは「|」で区切ることにより例外処理を纏めて記述できるようにした構文です。ここで注意する点は2点です。
1. 継承関係(ポリモーフィック)にある例外を併記することはできない
例えば、IOException
とException
を併記するとコンパイルエラーになります。
2. 変数は一つ
併記する例外がたくさんあっても、変数は最後に一つです。複数記述するとコンパイルエラーになります。
catch(IOException e1 | InterruptedException e2){} //コンパイルエラー
また、複数のcatch節がある場合、スーパークラスの例外の後にサブクラスの例外を記述することは出来ません(手前でキャッチされ検査できなくなるため)。
次に、これもSE7で導入されたtry-with-resource文。こちらは、SE 6以前ではfinally節でクローズ処理を記述していたもの(ex.FileReader
)を自動クローズできる仕組みを提供する構文です。
以下のように、tryの後ろ括弧内にリソースを定義することで仕組みが適用されます。
try(FileReader fr = new FileReader("sample1.txt");
FileWriter fw = new FileWriter("sample2.txt")){
//リソースの読み書き
}catch(IOException e){
//例外処理
}
ここで、クローズされる順番は定義した逆順となります。また、リソースを独自に定義している場合などでリソースがAutoClosable
かClosable
を実装していない場合、コンパイルエラーとなります。I/Oで普通用いられるクラスはAutoClosable
を実装している故問題なく実行できるわけです。
#ForkJoinPool
ForkJoinPoolでは実行用メソッドが3種類定義されています。このうち、処理の同期をとるのはinvokeのみ。
また、非同期の場合戻り値によって実行メソッドが変わります。以下にまとめました。
メソッド名 | 戻り値 | 同期/非同期 | 継承クラス |
---|---|---|---|
execute | void | 非同期 | RecursiveAction |
invoke | T | 同期 | RecursiveAction/RecursiveTask<V> |
submit | ForkJoinTask<T> | 非同期 | RecursiveTask<V> |
使っているメソッドを見て、invokeならば結果が一意に定まり、他なら不定になります。
#Scrollable ResultSet
JDBCにおけるResultSetでは、カーソルの移動を自由に行える仕組みを定義することができます。
//スクロール可能なResultSetを使用するためのStatement定義
Statement createStatement(int resultType, int resultSetConcurrency) throws SQLException
※デフォルトがスクロール不可のドライバとスクロール可のドライバが存在します。スクロール不可に出来ないものもあり、定数をスクロール不可にすると無視されます。(コンパイルエラーではない)
第一引数・第二引数に定義できる定数はResultSetインターフェースに定義されています。
- 第一引数
- TYPE_FORWARD_ONLY:順方向のみ移動
- TYPE_SCROLL_INSENSITIVE:スクロール可、DB非反映
- TYPE_SCROLL_SENSITIVE:スクロール可、DB反映
- 第二引数
- CONCUR_READ_ONLY:更新不可ResultSet
- CONCUR_UPDATABLE:更新可ResultSet
引数を取る際は2つ必要なため、1つのみの記述ではコンパイルエラーになります。
更新可能ResultSetにした場合、対象テーブルに主キーが設定されていればInsert、Update、Deleteの各操作が可能になりますが、insertRow
/updateRow
/deleteRow
メソッドを呼び出さなければ実際にDBへ反映されません。
#おわりに
GoldはSilverと比べ、覚える量・理解度の深さをかなり求められたと感じます。あまりに多くて気が滅入ることもしばしばありました。しかし、マイペースで良いので時間を掛けてじっくり取り組めば十分取得可能な資格だと思います。受験料がネックですが…
私は参考文献にある黒本による学習で合格できました。試験のみ考えるならこの本と公式APIの確認で十分です。より深い理解・完全正答を目指すなら、紫本など検討してみてもいいかもしれません…。
チャレンジして損はないと思います。javaの習得を考えている方、ぜひSilver、Goldの獲得を目指しましょう!