使用Class参数时,不会通过构造函数推断类型绑定?

时间:2012-10-18 17:07:10

标签: java generics type-inference

尝试理解为什么Java在使用Class参数传递类型信息时推断类型和检查类型边界时的行为方式不同。

以此代码为例:

public class TypeTest<T extends Number> {
    Class<T> type;

    TypeTest(Class<T> type) { this.type = type; }

    static <S extends Number> void sMethod(Class<S> type) {}

    <S extends Number>  void method(Class<S> type) {}


    public static void main(String[] args) throws InstantiationException, IllegalAccessException {
        // 1.
        TypeTest<Integer> obj = new TypeTest(Object.class);  // compiles, unchecked call and assignment warnings

        // 2.
        obj.method(Object.class); // compile-time error, S not within bound 

        TypeTest obj1 = new TypeTest(Object.class);  // compiles, unchecked call and assignment warnings

        // 3.
        obj1.method(Object.class); // compiles, unchecked call warning .             

        // 4.
        TypeTest.sMethod(Object.class); // compile time error, Object not within bounds

        // 5.
        new TypeTest<Object>(Object.class); // compile time error, Object not within bounds
    }

}

使用静态方法(4.)我们不能传递任何不是数字的东西,这似乎是提供边界的最自然的行为。

然而,对于构造函数(1.,5),我们必须明确指定类型参数以获得与4相同的行为。否则,似乎不会从Object.class变量自动推断T类型参数值。

构造函数和静态方法的区别在哪里?

另一个我完全不了解的情况是2.和3之间的区别。为什么同一个操作只根据TypeTest对象的构造方式编译或不编译,而类类型参数T没有任何关系方法类型参数S?

3 个答案:

答案 0 :(得分:1)

new TypeTest(Object.class)是原始类型TypeTest的表达式,就是它的设计方式。当然,没有类型推断,因为没有要推断的类型

答案 1 :(得分:1)

当您省略泛型类型的类型参数时 - 也就是说,只要您在没有TypeTest的情况下键入<Something>,Java就会忽略所有泛型检查< em>所有该类型。

有关详细信息,请参阅http://docs.oracle.com/javase/tutorial/java/generics/rawTypes.html

答案 2 :(得分:1)

只能推断为方法或构造函数声明的泛型类型。所以

<S> void method() {}
 ^ this can be inferred

<S> TypeTest() {}
 ^ this can be inferred

在构造泛型类时,无法推断泛型类的泛型类型:

class TypeTest<T> {}
               ^ this must be specified explicitly when using "new TypeTest"
                 or in Java 7 you can explicitly specify the diamond operator

正如其他人所提到的,当您使用new TypeTest()而没有任何尖括号时,您使用的是原始类型。原始类型必须与Generics之前的工作方式相同,以保持与旧代码的兼容性。因此,new TypeTest()表达式的类型为TypeTest(原始类型),而不是TypeTest<something>