JSR-202 Java Class File Specification Update

Type Signatureの文法がconflictしてるよねー、と知り合いに言われたので覚書。

原版

FormalTypeParameter:
        Identifier ClassBound InterfaceBound*
ClassBound:
        : FieldTypeSignature?
InterfaceBound:
        : FieldTypeSignature

現行javacの実装

FormalTypeParameter:
        Identifier ClassBound InterfaceBound*
        Identifier EmptyClassBound InterfaceBound+
ClassBound:
        : FieldTypeSignature
InterfaceBound:
        : FieldTypeSignature
EmptyClassBound:
        :

要は、「クラス境界を省略する場合は、1つ以上のインターフェース境界が必要」ということ。
JDK5とかJSE6のjavacでは、クラス境界とインターフェース境界がともに存在しない場合、クラス境界に明示的にjava.lang.Objectを指定している。つまり、「class A」は「A」ではなく「A」になる*1


で、上記javacの実装がリフレクションの挙動に影響を与えている(と思われる)。

http://java.sun.com/javase/ja/6/docs/ja/api/java/lang/reflect/TypeVariable.html

Type[] getBounds()
    この型変数の上限を表す Type オブジェクトの配列を返します。
    上限が明示的に宣言されない場合、上限は Object です。

とあるけど、普通は「上限が明示的に宣言されない場合、長さ0の配列を返します。」とかじゃないかなと。

一応確認。

public class A<T> {
    public static void main(String[] args) {
        Class<?> a = A.class;
        TypeVariable<?>[] typeParams = a.getTypeParameters();
        TypeVariable<?> t = typeParams[0];
        // -> [class java.lang.Object]
        System.out.println(Arrays.deepToString(t.getBounds()));
    }
}

Aでした。

*1:こうしないと、「class B」が「B」になってしまい、Yがシグネチャとコンフリクトする場合にあいまい: or