次のコードのコンパイル・実行結果として正しいものを選べ。
1 import java.util.*;
2 public class Q1 {
3 public static void main(String[] args) {
4 List<? extends Number> nums = new ArrayList<Integer>();
5 nums.add(1); // 行A
6 Number n = nums.get(0); // 行B
7 System.out.println(n);
8 }
9 }
- A行A でコンパイルエラーになる
- B
1が出力される - C行B でコンパイルエラーになる
- D実行時に
ClassCastExceptionがスローされる
正解・解説・誤答理由・ひっかけを見る▼ open
解説
List<? extends Number> は「Number の何らかのサブ型のリスト」を表すが、
その具体型はコンパイル時に不明。よって要素を追加しようとすると、引数がどの型に当てはまるか保証できず、
add は null 以外を受け付けない(上限付きワイルドカードは プロデューサ=読み取り専用。PECS の "Producer Extends")。
行A の nums.add(1) は型推論で受理されずコンパイルエラー。行B の get は要素を Number として安全に取り出せるため問題ない。- B行A でコンパイルが通らないため、そもそも実行されず出力に至らない。
- C行B の
getは? extends NumberからNumberとして取り出すので完全に合法。エラーにならない。 - Dコンパイルが通らない以上、実行時例外(ClassCastException)は発生し得ない。
? extends は読めるが書けない(null除く)。javac でコンパイルすると行Aで 「incompatible types: int cannot be converted to CAP#1 / no suitable method found for add(int)」系のエラー。 → コンパイル不成立(実行に至らない)。