Java Gold試験の最重要科目といえば「ジェネリクス」と「コレクション」です。 「ワイルドカード(?)が出てくると混乱する」「どのコレクションを選べばいいか迷う」という方も多いはず。
この記事では、試験で狙われるポイントを圧倒的なボリュームで徹底解説します。
1. ジェネリクス(汎用)の正体
ジェネリクスとは、クラスやメソッドで扱う**「データ型」をパラメータとして渡せる仕組み**のことです。
なぜジェネリクスが「型安全」なのか?
ジェネリクスが導入される前のJavaでは、あらゆる型を Object 型として扱っていました。しかし、それには2つの大きな問題がありました。
- キャストの手間: 取り出すたびに
(String)のようにキャストが必要。 - 実行時エラーのリスク: 違う型が混ざっていてもコンパイルで見抜けず、実行時に
ClassCastExceptionで落ちる。
ジェネリクスを使えば、不適切な型の代入をコンパイル時点でブロックできます。これが「型安全」の本質です。
2. 【最難関】境界ワイルドカードの完全理解
Java Goldで最も多くの受験生を悩ませるのが、extends と super を使った境界ワイルドカードです。
PECSの法則(Producer-Extends, Consumer-Super)
試験攻略の鍵は、この「PECSの法則」を脳に刻むことです。
① <? extends T>:上限境界
「Tまたはそのサブクラス」を許容します。
- 役割: データの「提供者(Producer)」。
- 特徴: 読み取り専用。リストから取り出すことはできますが、新しく要素を
addすることはできません(型が特定できないため)。
② <? super T>:下限境界
「Tまたはその親クラス」を許容します。
- 役割: データの「消費者(Consumer)」。
- 特徴: 書き込み可能。T型(またはそのサブクラス)の要素を安全に
addできます。
試験のひっかけパターン List<? extends Number> list = new ArrayList<Integer>(); list.add(10); // コンパイルエラー!
「IntegerはNumberを継承しているから追加できそう」と思わせるのが試験の罠です。extendsは「読み出し専用」と覚えましょう。
3. コレクションフレームワークの徹底比較
コレクションは、データの持ち方(データ構造)によって使い分けます。
List:順序と重複
- ArrayList: 内部が配列。インデックス指定の検索が爆速(O(1))。
- LinkedList: 要素同士がリンクで繋がっている。途中の挿入・削除に強い。
Set:重複排除とソート
- HashSet: ハッシュ値で管理。順序はバラバラだが検索が非常に速い。
- LinkedHashSet: 追加した順序を保持する。
- TreeSet: **値を自動でソート(昇順)**して保持する。
Map:キーと値のペア
- HashMap: キーの重複不可。非常に高速。
- TreeMap: キーでソートされる。
4. 【新設】実務での使い分けとパフォーマンス
文字数アップと専門性向上のため、実務の視点を追加します。
試験では「TreeSetはソートされる」という知識で十分ですが、実務では**「ソートが必要なら最初からTreeSetを使うか、後でCollections.sort()するか」**という議論がよく出ます。
- 大量のデータを扱う場合、毎回ソートが発生するTreeSetよりも、HashSetで集めてから最後にソートする方が速いケースもあります。
5. 実戦演習10問:クリックして回答をチェック!
SWELLの**「アコーディオンブロック」**を使用して作成しています。各「+」ボタンを押すと解答と解説が表示されます。
Q1:ジェネリクスの不変性
問題: 次のうち、コンパイルエラーになるものはどれか?
List<Number> l = new ArrayList<Integer>();List<? extends Number> l = new ArrayList<Integer>();List<? super Integer> l = new ArrayList<Number>();
解答
解答:1 解説: Javaのジェネリクスは「不変」です。たとえIntegerがNumberを継承していても、List<Number> に List<Integer> を入れることはできません。
Q2:PECSの法則(上限境界)
問題: List<? extends Number> list = new ArrayList<Integer>(); に対して list.add(10); を実行するとどうなるか?
解答
解答:コンパイルエラーになる 解説: extends(上限境界)は「読み取り専用」です。中身が何の型(IntegerかDoubleか)か特定できないため、null以外の追加は禁止されています。
Q3:TreeSetの特性
問題: TreeSet に “C”, “A”, “B”, “A” の順で追加した後の出力結果は?
解答
[A, B, C] 解説: Set なので重複した “A” は消え、TreeSet なので自然順序(昇順)に自動ソートされます。
Q4:HashMapの挙動
問題: HashMap に put("key", "val1") した直後、同じキーで put("key", "val2") するとどうなるか?
解答
値が “val2” に上書きされる 解説: Mapはキーの重複を許しません。上書きされた際、put メソッドは「古い値(”val1″)」を戻り値として返します。
Q5:ジェネリクスメソッド
問題: 文法的に正しいジェネリクスメソッドの宣言は? A: public <T> T method(T t) B: public T <T> method(T t)
回答
A 解説: 型パラメータ <T> の宣言は、戻り値の型の「前」に置く必要があります。 [SWELLアコーディオン終了]
Q6:LinkedListのメリット
問題: リストの「中間」への要素挿入が最も高速なのは?
ArrayListLinkedList
解答
2. LinkedList 解説: ArrayListは要素のシフト(移動)が発生しますが、LinkedListは参照の付け替えだけなので高速です。
Q7:Arrays.asListの制限
問題: Arrays.asList("A", "B").add("C"); を実行するとどうなるか?
解答
解答:UnsupportedOperationExceptionが発生する 解説: Arrays.asList で作られたリストは固定サイズです。要素の置換はできますが、追加や削除はできません。
Q8:下限境界ワイルドカード
問題: List<? super Integer> list = new ArrayList<Number>(); に対して list.add(10); は可能か?
解答
解答:可能 解説: super(下限境界)は「書き込み可能」です。Integerまたはそのサブクラスであれば安全に追加できます。
Q9:型消去(Type Erasure)
問題: ジェネリクスの型情報は実行時(Runtime)にも保持されるか?
解答
解答:保持されない(消去される) 解説: コンパイル時に型チェックが行われた後、型情報は削除されます(Object等に置換)。これを型消去と呼びます。
Q10:Dequeのスタック操作
問題: Deque をスタック(LIFO)として使うための適切なメソッドは?
解答
解答:push() と pop() 解説: Deque インターフェースは push で先頭追加、pop で先頭削除を行うことでスタック動作を実現します。
まとめ:合格へのチェックリスト
- [ ] extends は読み出し専用、super は書き込み用
- [ ] TreeSet と TreeMap は「ソート」がキーワード
- [ ] List は List のサブタイプではない(AがBを継承していても)
[参考リンク] より深い内部構造を知りたい方はOracle公式:コレクションの概要(外部リンク)を読み込みましょう。


コメント