尝试理解为什么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?
答案 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>
。