Goldは、型・ジェネリクス・ストリーム・並行処理・I/Oなどのルールが組み合わされたコードを正確に読む試験です。似たAPI名を暗記するより、型がどう流れ、いつ評価され、どこで共有状態が生まれるかを可視化します。
更新日 2026-10-05
Java SE 17 Programmer II(Gold) 攻略ガイド
Goldで迷うのは、API名を知らない場面だけではありません。ジェネリクスの型は読めるのに追加可能な値を取り違える、Streamの途中で型が変わったことに気付かない、並行処理の実行順を一つに決めてしまう。複数の規則が重なったコードで、APIの約束を守って判断する力を育てます。
このガイドでは、型の流れ、評価される時点、共有される状態、リソースの寿命を中心に読み方を整理します。コードを何度も実行して一つの結果を覚えるより、「保証されること」と「実行条件で変わること」を説明できる状態を目指します。
このページ内のミニケース、コード、計算例は、学習方法を説明するために資格合格.webが独自に作成したものです。実際のJava SE 17 Programmer II(Gold)の非公開試験問題を転載・再現したものではありません。
Goldを始める前に、Silverの読み方を点検する
参照型と実体、オーバーロードとオーバーライド、チェック例外の宣言に迷う場合は、該当する言語規則を先に復習します。GoldのAPIを増やしても、土台の型判定が揺れていると、Streamやラムダの途中で候補を誤ります。
2026-10-05確認時点のOracle試験案内では、1Z0-826-JPNは選択問題・90分・60問です。配信終了試験一覧にはSE 17試験の2027年2月28日配信終了予定が掲載されています。受験までの期間、認定パス、保有資格による条件は公式案内と資格情報ページで確認してください。
学習環境はJava 17へ合わせます。特に並行処理は後の版で使えるAPIと混ぜないようにし、Java 17のJavadocを開いて対象バージョンの契約を読みます。
ジェネリクスは、読める型と書ける値を別々にする
List<Integer> を List<Number> としてそのまま扱えないのは、Numberのリストとして別の数値型を追加できてしまうと安全性が崩れるためです。要素型の継承関係と、リスト型の代入可能性を同一視しないでください。
extends/super
extends/super。List<Integer>:Integerとして取り出し、Integerを追加できる。List<Number>へそのまま代入は不可。 List<? extends Number>:取り出しはNumberで受ける。具体的な要素型が不明なので、null以外の値は追加不可。 List<? super Integer>:Integerを追加できる。取り出しを安全に受ける型はObjectで、Integerとは決められない。 本文例の結果は4:5:sourceからNumber first=4、targetからObject value=5。source.add(6)はコンパイル不可。
- List<Integer>Integerとして取り出し、Integerを追加できる。List<Number>へそのまま代入は不可。
- List<? extends Number>取り出しはNumberで受ける。具体的な要素型が不明なので、null以外の値は追加不可。
- List<? super Integer>Integerを追加できる。取り出しを安全に受ける型はObjectで、Integerとは決められない。
- 本文例の結果は4:5sourceからNumber first=4、targetからObject value=5。source.add(6)はコンパイル不可。
| 宣言型 | 取り出した値を安全に受ける型 | null以外を追加するときの考え方 |
|---|---|---|
List<Integer> | Integer | Integerを追加できる |
List<? extends Number> | Number | 実際の要素型が不明なので、任意のNumberは追加できない |
List<? super Integer> | Object | Integerを追加できるが、取り出しをIntegerとは決められない |
次はメソッド内に置ける例です。importを省略して、型の境界に集中しています。
java.util.List<Integer> ints = new java.util.ArrayList<>();
ints.add(4);
java.util.List<? extends Number> source = ints;
Number first = source.get(0);
java.util.List<? super Integer> target = new java.util.ArrayList<Number>();
target.add(5);
Object value = target.get(0);
System.out.println(first + ":" + value);
出力は 4:5 です。次に source.add(6); を追加するとコンパイルできません。source が別のNumberのサブタイプのリストを参照している可能性を、宣言型だけでは排除できないためです。Integer result = target.get(0); も、そのままでは成立しません。
復習では「extendsは読む、superは書く」という短い言葉の後に、どの型として安全かを必ず補います。上限境界付きの型パラメータ、ワイルドカード、型消去も、宣言の形と使用できる操作を並べて整理します。
コレクションの契約を、データの置き方から選ぶ
Listは順序と添字、Setは重複、Mapはキーと値の関係に注目します。重複や検索の練習では、equals と hashCode の整合性も点検します。ソートではComparatorが返す数値の符号を読み、昇順・降順を値の大小から説明します。
ミニケースとして、部署ごとに社員名をまとめたい場合を考えます。まず一人を一つの要素として表す型を決め、次に部署をキーにするMapと、同じ部署の複数人を保持するListの役割を分けます。最終的な戻り値の型を先に書くと、後でCollectorsを学ぶときにも目的が見えます。
List.of などで作る変更できないコレクションを、ArrayListと同じ感覚で更新しないことも大切です。参照先を変更できるか、要素を追加できるか、要素オブジェクトの内容を変更できるかは、別々に確認します。
Streamは、各段階の要素型を書いてから値を流す
Streamパイプライン
Streamパイプライン。stream:文字列の流れ:wordsからStream<String>を作る。要素はred、blue、gold。 filter:型を保って選別:長さ4以上を残す。Stream<String>のままで、通過するのはblueとgold。 mapToInt:数値へ変換:String::lengthで長さへ写す。型はIntStreamになり、値は4と4。 sum:終端操作:終端操作で集計しintの8を得る。中間操作の宣言だけでは集計は完了しない。
- stream:文字列の流れwordsからStream<String>を作る。要素はred、blue、gold。
- filter:型を保って選別長さ4以上を残す。Stream<String>のままで、通過するのはblueとgold。
- mapToInt:数値へ変換String::lengthで長さへ写す。型はIntStreamになり、値は4と4。
- sum:終端操作終端操作で集計しintの8を得る。中間操作の宣言だけでは集計は完了しない。
java.util.List<String> words = java.util.List.of("red", "blue", "gold");
int total = words.stream()
.filter(s -> s.length() >= 4)
.mapToInt(String::length)
.sum();
System.out.println(total);
出力は 8 です。最初は Stream<String>、filterの後も Stream<String>、mapToIntの後は IntStream になります。filterは通過する要素を減らし、mapToIntは要素を数値へ変換し、sumが集計します。「すべてStream」という読み方では、次に使える操作が分かりません。
中間操作だけをつないでも、その時点で一連の処理が完了したとは考えません。終端操作の存在、短絡する操作か、順序が必要かを確認します。特にpeekなどの副作用について、すべての要素で必ず実行される前提の解き方は避けます。Streamの公式APIの契約へ戻って確認してください。
mapとflatMapは、戻り値の形で比較します。一要素から一つの値へ変換するのか、一要素から得た複数要素の流れを平らにつなぐのかを、Stream<List<String>> と Stream<String> の違いとして書きます。reduceでは単位元や結合関数を確認し、並列化しても意味が保たれるかを考えます。
Optionalでは、空の状態と評価タイミングを分ける
Optional評価
Optional評価。値あり:ready:valueはOptional.of("ready")。以下は本文の二つのprintlnを順番に追う。 orElseの引数を評価:fallback()を先に呼びFを出力。代替値backupを引数として渡す。 orElseの返却値を表示:値が存在するのでreadyを返す。printlnまで含め一行目はFready。 orElseGetを評価:値ありのためSupplierを呼ばずreadyを返す。二行目はreadyでFは出ない。
- 値あり:readyvalueはOptional.of("ready")。以下は本文の二つのprintlnを順番に追う。
- orElseの引数を評価fallback()を先に呼びFを出力。代替値backupを引数として渡す。
- orElseの返却値を表示値が存在するのでreadyを返す。printlnまで含め一行目はFready。
- orElseGetを評価値ありのためSupplierを呼ばずreadyを返す。二行目はreadyでFは出ない。
Optional.of(null)、Optional.ofNullable(null)、空のOptionalからの get() は、同じ結果にはなりません。値が存在しないことと、Optional変数自体がnullであることも分けます。
次の完全な例は、値が存在するときの代替値の評価を確認するものです。
class Main {
static String fallback() {
System.out.print("F");
return "backup";
}
public static void main(String[] args) {
java.util.Optional<String> value = java.util.Optional.of("ready");
System.out.println(value.orElse(fallback()));
System.out.println(value.orElseGet(Main::fallback));
}
}
一行目は Fready、二行目は ready です。orElseでは、メソッドへ渡す引数の式としてfallbackを先に評価します。orElseGetでは、値があるためSupplierの処理を呼びません。「どちらも代替値を返すメソッド」とまとめず、呼び出す条件と処理コストを分けます。Optionalの公式APIで、値あり・空の両方を確認します。
ラムダとメソッド参照は、対象となる関数型インタフェースの引数と戻り値へ対応付けます。Predicate、Function、Consumer、Supplierを名前だけで覚えず、判定する、変換する、受け取って処理する、値を供給する、という処理の形にします。キャプチャするローカル変数の条件や、チェック例外も点検します。
並行処理では、出力順より先に共有状態を探す
共有状態
- 共有する更新対象二つのタスクが同じcountを更新。count++は読取・加算・書込が一体とは限らない。
- 競合する一例両タスクが0を読み、各々1を書けば最終値は1。二回の加算でも2が保証されない。
- 共通ロックで保護synchronizedで同じロックを使い更新全体を保護する。別々のロックでは互いを排除できない。
- 終了要求と待機も別shutdown()は完了待ちではない。Future.get()は結果、awaitTermination()は終了を待つ。
二つのタスクが同じカウンタへ count++ を行う例では、読み取り・加算・書き込みが一つの不可分な操作とは限りません。何度か期待値が出ても、それだけで安全だとは判断できません。共有する変数、更新する箇所、排他制御の対象を先に囲みます。
synchronizedは、どのロックを共有しているかが重要です。タスクごとに異なるオブジェクトをロックしていたら、同じ更新を互いに排除する根拠にはなりません。並行コレクションを使用する場合も、個々のメソッドの安全性と、複数操作を合わせた手順の安全性を分けて読みます。
ExecutorServiceでは、タスクの提出、結果の取得、終了要求、終了確認を一本の時間軸に置きます。shutdown() は提出済みタスクの完了をその場で待つ操作ではありません。Future.get() と awaitTermination() は何を待つかが違います。Java 17のExecutorServiceの契約を確認し、後のJavaで利用できる終了処理を混ぜないようにします。
並列Streamでは、「どの要素が先に処理されたか」と「最終結果で順序が求められるか」を別に考えます。実行結果の一回分を正解とするのではなく、契約上あり得る結果と保証されない順序を説明してください。
ファイル操作は、パス・実体・寿命の三つで読む
NIO/I-Oフロー
NIO/I-Oフロー。Path:場所を表す:Path.of("sample.txt")はパスを作るだけ。ファイルの実体は作成しない。 Files.lines:開く:存在するUTF-8ファイルを開きStream<String>を得る。失敗時は例外経路を確認。 filterとcount:読む:空白行を除いて件数を数える。終端操作count()の結果はlong。 try終了:閉じる:try-with-resourcesでStreamを閉じる。処理中に例外が起きても終了時の解放を行う。
- Path:場所を表すPath.of("sample.txt")はパスを作るだけ。ファイルの実体は作成しない。
- Files.lines:開く存在するUTF-8ファイルを開きStream<String>を得る。失敗時は例外経路を確認。
- filterとcount:読む空白行を除いて件数を数える。終端操作count()の結果はlong。
- try終了:閉じるtry-with-resourcesでStreamを閉じる。処理中に例外が起きても終了時の解放を行う。
Pathを生成しただけでは、ファイルやディレクトリの作成は行われません。パスを正規化する操作と、ファイルシステムの実体へアクセスする操作も違います。コピー、移動、存在確認では、元の状態とオプションを先に書きます。
Filesで取得するStreamを読む場合は、閉じる責任も確認します。次の例はUTF-8の sample.txt が存在する前提で、チェック例外を扱えるメソッド内へ置きます。
try (java.util.stream.Stream<String> lines =
java.nio.file.Files.lines(java.nio.file.Path.of("sample.txt"))) {
long count = lines.filter(line -> !line.isBlank()).count();
System.out.println(count);
}
空白だけの行を除いた行数を表示し、tryの終了時にStreamを閉じます。ファイルがない場合や読み取りに失敗する場合は、正常時の行数を追う前に例外経路を考えます。Filesの公式APIで、戻り値とリソース管理をセットで確認します。
シリアライゼーションでは、保存される状態、staticやtransientの扱い、復元時の初期化を区別します。I/O全体を一つの暗記一覧にせず、読む対象と閉じる対象がどのオブジェクトなのかを図へ書きます。
モジュール、JDBC、ローカライズも取り残さない
Streamや並行処理だけがGoldではありません。モジュールは、パッケージの公開と依存するモジュールの宣言を分けます。requires と exports の向き、通常のアクセス修飾子を、二つのモジュールの関係図へ書きます。ServiceLoaderはサービスを使う側と提供する側の宣言へ結び付けます。
JDBCでは、接続、SQLの準備、パラメータ設定、実行、結果の読み取り、クローズという順で練習します。PreparedStatementのパラメータ添字は1から始まります。ResultSetの行位置と、SQLへ値を渡す添字を混同しないようにしてください。PreparedStatementの公式APIで実行メソッドの戻り値も確かめます。
ローカライズではLocale、リソースバンドル、数値や日付のフォーマットを分けます。デフォルトの地域設定に任せた実行結果と、Localeを明示した結果を比較すると、環境に依存する箇所を発見できます。
復習は、APIの名前ではなく契約の読み違いへ戻る
Gold学習サイクル
Gold学習サイクル。契約の読み違いを記録:宣言型・戻り値・評価時点・例外・リソース終了から、間違えた根拠を選ぶ。 APIの契約へ戻る:型の安全性か、代替処理の評価か、終了と待機か。Javadocで保証を確認する。 前提を一つ変えて演習:Optionalを空にするなど条件を変更。単独APIの後は型とラムダ等の組合せも練習。 保証を根拠に再判定:コンパイル可否→型→評価時点の順で説明。迷った契約を次の復習へ戻す。
- 契約の読み違いを記録宣言型・戻り値・評価時点・例外・リソース終了から、間違えた根拠を選ぶ。
- APIの契約へ戻る型の安全性か、代替処理の評価か、終了と待機か。Javadocで保証を確認する。
- 前提を一つ変えて演習Optionalを空にするなど条件を変更。単独APIの後は型とラムダ等の組合せも練習。
- 保証を根拠に再判定コンパイル可否→型→評価時点の順で説明。迷った契約を次の復習へ戻す。
Goldの間違いノートには、宣言型、入力、戻り値型、評価時点、例外、リソースの終了を必要に応じて記録します。すべてを毎回埋める必要はありません。間違えた根拠に関係する欄を選びます。
例えば「orElseGetを使っていても代替処理が先に実行されると思った」なら評価時点、「extendsのリストへNumberを追加した」なら型の安全性、「shutdownの直後なら結果が完成していると思った」なら終了と待機の混同へ戻ります。同じAPIを何十回も読むより、誤った前提を一つ変える演習を作ります。
学習教材で単独のAPIを確認したら、問題演習で二つの規則を組み合わせます。型推論とラムダ、OptionalとStream、ファイル走査とリソース管理のように、組み合わせごとに説明できるか確かめます。弱点分析では「並行処理が苦手」から「共有ロックの対象を見落とす」まで原因を具体化します。
模擬試験では、APIの詳細を思い出す前に、コンパイル可能か、どの型が流れるか、いつ評価するかの順で候補を絞ります。実行環境を使わずに判断した後、保証の根拠をJavadocやJava 17言語仕様の型で確認します。料金や配信方法、認定条件の最終確認は資格情報ページからOracle公式へ進んでください。