【合格体験記】Java Gold SE 11に合格したので振り返ってみる

はじめに

先日、Java Gold(Oracle Certified Java Programmer, Gold SE 11)に合格したので、ぼちぼち振り返りをしていこうと思います。
実際の試験対策のみ気になる方は「試験対策について」をご覧になってください!
この記事では私が実践した学習法や試験対策について紹介していきます。少しでもJava Goldを目標としている皆さんの学習のヒントになれば幸いです。

学習ロードマップ

Step 1:基礎理解フェーズ – 紫本を「動かす教科書」にする

 最初のステップは、教科書である「紫本」を使い、試験範囲の知識をインプットすることです。ただ読むだけでなく、手を動かして知識を体感することを重視しました。

  • 学習法
    紫本を読み進めながら、不明な部分は紫本に記載のサンプルコードをエディタに書き写し、自分でコンパイル&実行しました。
    「なぜこの結果になるのか」を自分の目で確かめることで、知識の定着度が格段に上がります。
  • 問題演習
    章末問題は2周しました。正直なところ紫本の問題は黒本より難解に感じました。
    そのため、ここでは満点を目指すというよりは「知識の確認」と割り切り、深追いしすぎないようにしました。実践力は次の黒本で鍛える、という明確な線引きが重要です。
    「問題演習はあくまでも黒本を中心にやる」ということを最初から考えていたので、正答率があまり上がらなくてもそこまで気にしていませんでした。

<< 実際の紫本学習記録 >>

正答率63%以上になった場合は赤文字で表示されるようにしていますが、やはり1周目は散々な結果になっていますね、、、
ただ、そこまで気にしなくてもOK。本腰入れて問題演習するのは黒本です。
紫本を購入すると、模擬試験1回分をPDFダウンロードできるようになるのですが、結局やりませんでした笑

Step 2:実践演習フェーズ – 黒本で「なぜ」を極め、模試で仕上げる

紫本で基礎をインプットしたら、次は問題集である「黒本」でアウトプット中心の学習に移行します。ここが合格への最重要ステップであり、模擬試験による総仕上げまで含みます。

章別問題の周回

まずは模擬試験以外の1〜12章をひたすら周回します。ここでの目的は「答えを暗記するのではなく、なぜその選択肢が正解で、他の選択肢が不正解なのかを完璧に説明できること」です。少しでも挙動が怪しいコードは、面倒でも必ず自分で書いて動かしてみる、この地道な作業が後で効いてきます。各章で安定して90%近くの正答率を出せるようになったら、次の模擬試験に進みます。
紫本は別途PDFをダウンロードする必要がありますが、黒本は最終章が模擬試験となっています。

合格を盤石にする「黒本・模擬試験」徹底活用法

各章の基礎が固まったら、いよいよ最後の仕上げの模擬試験です。
単に点数を測るのではなく、戦略的に弱点を潰すために活用します。

  • 模擬試験1回目:弱点把握と詳細な振り返り
    各章を完璧にしたつもりでも、総合問題となる模擬試験でいきなり合格点を取るのは難しいです。私の最初の点数も60%前後でした。ここで落ち込む必要は全くありません。最も重要なのは「振り返り」です。間違えた問題はもちろん、すべての問題の選択肢をレビューし、「なぜ違うのか」を徹底的に分析します。
  • 模擬試験2回目:満点を目指し、「理解が曖昧な正解」を潰す
    1回目の詳細なレビューを終えたら、2回目は満点を目指します。そして、ここでの振り返りで重要なのは、間違えた問題だけでなく、「正解はしたものの、少しでも理解が怪しかった問題」も洗い出すことです。この「曖昧な正解」が本番での失点に繋がります。
  • 模擬試験3回目:総仕上げ
    これまでのレビューで洗い出した弱点をすべて潰し、万全の状態で挑みます。ここでも目標は満点です。ここまでやり込めば、本番でも自信を持って問題に臨める実力がついているはずです。

<< 実際の黒本学習記録 >>

黒本の学習記録については、
・1周目:65%以上が赤文字
・2周目:90%以上が赤文字
・3周目:100%が赤文字
となるように表示設定をしています。
黒本に関しては紫本とは異なり、全ての単元で90%以上を取れるようになるまで問題演習を繰り返しました。

各単元の問題演習ももちろん重要ですが、合格のためには最後の模擬試験が非常に重要です。
正答率100%になるまで繰り返しました。

試験対策について

実際に試験を受けてみて、やはり下記単元からの出題が多かった印象です。

  • 関数型インタフェースとラムダ式
  • ストリームAPI
  • コレクションとジェネリックス

出題問題数は80問ですが、60%くらいはこれらの単元だったような、、、

最頻出分野のピンポイント対策

 下記3単元を完璧にしておいて正答率50%~60%は確保、残りはモジュールシステム・例外処理・JDBCの丸暗記などで正答率を上積みしていく作戦で十分合格できるかと思います。(あくまでも私の感想です)

<<Stream API:最重要かつ最難関>>

 Java Goldの合否はStream APIの習熟度で決まると言っても過言ではありません。私が特に重要だと感じたのは以下の3点です。

1.中間操作と終端操作の完全な理解

filterやmapといった「中間操作」と、collectやforEachといった「終端操作」の違いを明確に区別できることが大前提です。終端操作が呼び出されるまでストリームの処理は実行されない(遅延評価)という基本原則を、様々なコードで体感しておく必要があります。

2.Stream<T>とプリミティブStreamの使い分け

Stream<Integer>とIntStreamは似て非なるものです。IntStreamのようなプリミティブストリームは、内部的にint値として扱われるため効率的で、sum()やaverage()といった専用の集計メソッドを持っています。
一方でcollectを使えるのはStream<T>だけです。どちらのストリームで、どのメソッドが使えるのか、その棲み分けを正確に覚えておくことが、多くの選択肢問題で役立ちます。

3.collectメソッド、特にグルーピングの理解

collectメソッドは非常によく出題され、特にCollectorsクラスを使ったグルーピングは頻出です。主なパターンとして分類と分割の2つを確実に押さえましょう。

groupingBy

指定したキーごとに要素をグループ化します。
戻り値はMap<K, List<V>>です。

List<String> fruits = List.of("apple", "banana", "cherry", "avocado");
// 文字数でフルーツを分類
Map<Integer, List<String>> grouped = fruits
                                      .stream()
                                      .collect(Collectors.groupingBy(String::length));
                                      
// 結果: {5=[apple], 6=[banana, cherry], 7=[avocado]}

partitioningBy

条件式(Predicate)に基づき、要素をtrueとfalseの2つのグループに分割します。
戻り値はMap<Boolean, List<V>>です。

List<String> fruits = List.of("apple", "banana", "cherry", "avocado");
// 文字数が5より大きいかどうかでフルーツを分割
Map<Boolean, List<String>> partitioned = fruits
                                          .stream()
                                          .collect(
                                            Collectors.partitioningBy(s -> s.length() > 5));
                                                    
// 結果: {false=[apple], true=[banana, cherry, avocado]}

<<関数型インタフェース(ラムダ式):ルールを覚えれば得点源になる>>

ここはめちゃくちゃ安パイです。
一見すると複雑に見えるラムダ式ですが、構文のルールは決まっています。このルールさえマスターしてしまえば、むしろ確実に点が取れる「ラッキー問題」になります。
回答までに10秒もかからず、問題を見た瞬間に答えが分かるようになります。

1.省略ルールについて

下記の省略ルールを瞬時に判断できるようになれば、ラムダ式の問題は得点源に変わります。
ちなみに引数で型宣言した場合は()を省略することは出来ません。
※ひっかけ的に、varを使って引数で型宣言をしているのに()でくくられていない選択肢などもよく出てきます。
もちろんvarを使った型宣言であっても()は必要です

//【最も丁寧な形】型宣言あり, カッコあり, 波カッコ・returnあり
Predicate<String> p1 = (String s) -> { return s.isEmpty(); };

//【一般的な形】型宣言省略, カッコあり, 波カッコ・return省略
Predicate<String> p2 = (s) -> s.isEmpty();

//【最も簡潔な形】引数が一つのためカッコも省略
Predicate<String> p3 = s -> s.isEmpty();

2.関数型インタフェースの引数・戻り値について

下記に挙げた関数型インタフェースについては覚えてしまいましょう。
仕組みを覚えれば簡単に覚えられます。

インタフェース名を見れば、なんとなーくどういった機能を持ったものなのかは予測も出来ます。
例えば、"Supplier"だと「供給」だから何かを戻すんだろうなとか、"Consumer"だと「消費」だから引数を受け取るんだろうなとか、
結構名前で判断できたりします。
Supplier

引数なし、戻り値ありのインターフェースです。何かを供給(supply)する役割を担います。
抽象メソッド:T get()

import java.util.function.Supplier;
import java.time.LocalDate;

// 現在の日付を提供するSupplier
Supplier<LocalDate> dateSupplier = () -> LocalDate.now();

// get()メソッドで値を取得
LocalDate today = dateSupplier.get();
System.out.println("今日の日付は: " + today);

// 実行結果:
// 今日の日付は: 2025-10-11

Consumer

引数あり、戻り値なしのインターフェースです。引数を受け取って何かを消費(consume)する処理を行います。
抽象メソッド:void accept(T t)

import java.util.function.Consumer;

// 文字列を大文字にして出力するConsumer
Consumer<String> upperCasePrinter = (s) -> System.out.println(s.toUpperCase());

// accept()メソッドで処理を実行
upperCasePrinter.accept("hello");

// 実行結果:
// HELLO

Predicate

引数あり、戻り値はbooleanのインターフェースです。引数が特定の条件を満たすかどうかを判定(predicate)します。
抽象メソッド:boolean test(T t)

import java.util.function.Predicate;

// 数値が正かどうかを判定するPredicate
Predicate<Integer> isPositive = (number) -> number > 0;

// test()メソッドで条件を評価
boolean result = isPositive.test(10);
System.out.println("10は正の数ですか? " + result);

// 実行結果:
// 10は正の数ですか? true

Function

引数あり、戻り値ありのインターフェースです。引数を別の型の値に変換する機能(function)を提供します。
抽象メソッド: R apply(T t)

import java.util.function.Function;

// 文字列をその長さに変換するFunction
Function<String, Integer> stringLengthFunction = (s) -> s.length();

// apply()メソッドで変換を実行
int length = stringLengthFunction.apply("Function");
System.out.println("'Function'の長さは: " + length);

// 実行結果:
// 'Function'の長さは: 8

UnaryOperator

引数と戻り値が同じ型である特殊なFunctionです。Functionの特殊系と覚えておきましょう。
例)Function<String, String>UnaryOperator<String>になります。
抽象メソッド: T apply(T t)

import java.util.function.UnaryOperator;

// 整数を2乗するUnaryOperator
UnaryOperator<Integer> square = (n) -> n * n;

// apply()メソッドで操作を実行
int squaredValue = square.apply(5);
System.out.println("5の2乗は: " + squaredValue);

// 実行結果:
// 5の2乗は: 25

BinaryOperator

2つの引数と戻り値がすべて同じ型である特殊なFunctionです。これもFunctionの特殊系と覚えておきましょう。
例)Function<String, String, String>BinaryOperator<String>になります。
抽象メソッド: T apply(T t, T u)

import java.util.function.BinaryOperator;

// 2つの整数を加算するBinaryOperator
BinaryOperator<Integer> adder = (a, b) -> a + b;

// apply()メソッドで計算を実行
int sum = adder.apply(10, 20);
System.out.println("10と20の合計は: " + sum);

// 実行結果:
// 10と20の合計は: 30

<<コレクションとジェネリックス:基本だからこそ正確に>>

Stream APIやラムダ式と密接に関わるため、コレクションフレームワークの正確な理解は必須です。

List, Set, Mapの特性の違い

「Listは順序を保持して重複OK」
「Setは順序不定で重複NG」
「Mapはキーと値のペア」
という基本を、ArrayList, HashSet, HashMapといった代表的な実装クラスの挙動とセットで完璧に理解しておく必要があります。

getとgetPropertyメソッドの違いの理解

Mapの中でも特殊なPropertiesクラスの挙動は問われやすいポイントです。MapのgetとPropertiesのgetPropertyは似ていますが、重要な違いがあります。

getメソッド (Mapインターフェース)
Mapインターフェースで定義されている、最も基本的で汎用的な値取得メソッド
引数:Object key
戻り値:マップの値の型
┗キーが見つかった場合は、それに対応する値を返す。 キーがマップ内に存在しない場合は null を返す。

getPropertyメソッド (Propertiesクラス)
Propertiesクラス独自のメソッドで、キーと値が文字列であることを前提
引数:① String keyString key, String defaultValue (オーバーロードして引数が二つある場合)
戻り値:String (文字列)
┗①キーが見つからない場合は null を返す。
┗②キーが見つからない場合は、defaultValueで指定したデフォルト値を返す。

import java.util.Properties;

public class Example {
    public static void main(String[] args) {
        Properties props = new Properties();
        props.setProperty("user.name", "Taro");

        // getメソッドの使用
        String userName1 = (String) props.get("user.name"); // "Taro"
        String userPass1 = (String) props.get("user.pass"); // null

        // getPropertyメソッドの使用
        String userName2 = props.getProperty("user.name");           // "Taro"
        String userPass2 = props.getProperty("user.pass");           // null
        String userPass3 = props.getProperty("user.pass", "default"); // "default"

        System.out.println("パスワード1: " + userPass1);
        System.out.println("パスワード2: " + userPass2);
        System.out.println("パスワード3: " + userPass3);
    }
}

おわりに

試験結果について

今回もSilverの時の振り返りと同様、一応試験結果も載せておきますね
ちゃんと受かってますからね!!!

Silverの正解率は89%だったので、ほんの少しだけ下がってしまいましたね、、、
試験時の体感としてはSilverの時よりも早く終わりましたし、簡単なように感じたんですけどね、、、

試験を受験した感想

端的に言えば「JavaSilverとは別物だな」という感想です。
・JavaSilverは「自分がコンパイラになったつもり」で問題を解く
・JavaGoldは「Javaに関する知識やコーディングに関する知識」で問題を解く
というような感じです。
実務でJavaを使われている方であれば、もしかするとGoldの方が簡単と思われるかもしれません。
(ただ、Goldを受験するためにはSilverの合格が必須となっているので、どのみちSilverの受験はしなければならないのですが、、、)
試験時間は180分なのですが、おそらく「60分:回答・15分:見直し」くらいだった記憶です。Silverの時と比べてもだいぶ早く終わりました。
正直、黒本の内容を覚えるぐらい勉強すれば余裕なのかなという感じです。まあ、そこまでが大変なのですが笑

やはり重要となるのはストリームAPI、関数型インタフェース、コレクションとジェネリックスです。
この3単元に関しては黒本の内容について、「どうしてこの選択肢が正解なのか」を説明出来るくらいになっておくべきかと思いました。
あとは例外処理やクラスの基礎知識(インナークラスや匿名クラス)もぼちぼち出題されたかなという感じです。
おぼろげながらモジュールシステムやJDBCなども出題されていた記憶がありますが、ここら辺は丸暗記でも十分戦えます。
アサーションは出題されていなかった気がしますが、黒本の単元で触れられていた部分さえ理解していれば問題ないかと思います。

これから挑戦する方々は、不安も大きいかと思いますが、正しい方法で学習を続ければ必ず合格できる試験です。この記事が、少しでもその手助けになれば幸いです。
頑張ってください!

<<関連記事>>

櫟原侑祐

 櫟原侑祐

スキル:Java/SpringBoot/Spring/Kotlin/Bootstrap/Thymeleaf/HTML/CSS/JavaScript/TypeScript/Angular/MySQL/PostgreSQL/MongoDB/Eclipse/Spring Tool Suite4/Android Studio/A5:SQL Mk-2/MongoDB Compass/GitHub

コメント

この記事へのコメントはありません。

関連記事