Eclipseで見えるワイルドカード配列

概要

Eclipseでは、メソッド呼び出しの式の型が見える。
そこでは、ワイルドカード配列らしきものが見える。

package test;

public class WildcardTest {

    // 型パラメータT
    static class C<T> {
        public T getT() {
            return null;
        }
        
        public T[] getTArray() {
            return null;
        }
    }
    
    private interface I {/**/}
    
    public static void main(final String[] args) {
        // T = ?
        C<?> c1 = new C<I>();
        Object o1 = c1.getT(); // ?
        Object[] a1 = c1.getTArray(); // ?[]
        
        // T = ? extends I
        C<? extends I> c2 = new C<I>();
        Object o2 = c2.getT(); // ? extends I
        I[] a2 = c2.getTArray(); // ? extends I[]
        
        // T = ? extends I[]
        C<? extends I[]> c3 = new C<I[]>();
        I[] o3 = c3.getT(); // ? extends I[]
        I[][] a3 = (I[][]) c3.getTArray(); // ? extends I[][]
        
        // T = ? super I
        C<? super I> c4 = new C<I>();
        Object o4 = c4.getT(); // ? super I
        Object[] a4 = c4.getTArray(); // ? super I[]
    }
}

やり方まとめ

  1. 型パラメータTを持つクラスCが、Tを返すメソッドgetT() とT[] を返すメソッドgetTArray()を持つとする。
  2. C<?> 型の変数を用意する。
  3. その変数に対してgetTを呼ぶ式を書き、Eclipseエディタでカーソルをあわせると ? が見える。
  4. その変数に対してgetTArrayを呼ぶ式を書き、Eclipseエディタでカーソルをあわせると ?[] が見える。
  5. C<? extends I> や C<? extends I[]>、C<? super I> なども同様。

表記のパース

c2.getTArray() と c3.getT() を見比べれば分かる通り
Eclipse上の表記では (? extends I)[] と ? extends (I[]) が同じ表記になることがわかった。(丸括弧は便宜上のもの)

Eclipseの型付け

Eclipseでは c3.getTArray() (型は(? extends I[])[] と考えられる) をキャストなしで I 型の変数に代入できなかった。
Oracleコンパイラだと問題なくできるようだけれども。