在收藏方面,我理解泛型。但是在Class<T>
类的情况下它意味着什么?实例化Class
对象时,只有一个对象。那么为什么T
参数呢?这是什么规定的?为什么有必要(如果有的话)?
答案 0 :(得分:47)
类型参数<T>
已添加到java.lang.Class
以启用一个特定的习惯用法 1 - 使用Class
个对象作为类型安全的对象工厂。实质上,<T>
的添加允许您以类型安全的方式实例化类,如下所示:
T instance = myClass.newInstance();
类型参数<T>
表示类本身,通过将Class<T>
存储在泛型类中或将其作为参数传递给泛型方法,可以避免类型擦除的不良影响。请注意,T
本身不足以完成此任务 2 :T
的类型被删除,因此它变为java.lang.Object
。< / p>
这是一个典型的例子,其中类的<T>
参数变得重要。在下面的示例中,Java编译器能够确保类型安全,允许您从SQL字符串和Class<T>
实例生成类型集合。请注意,该类用作 factory ,并且可以在编译时验证其类型安全性:
public static <T> Collection<T> select(Class<T> c, String sqlStatement) {
Collection<T> result = new ArrayList<T>();
/* run sql query using jdbc */
for ( /* iterate over jdbc results */ ) {
T item = c.newInstance();
/* use reflection and set all of item’s fields from sql results */
result.add(item);
}
return result;
}
由于Java会删除type参数,使其成为java.lang.Object
或指定为泛型upper bound的类,因此访问{{1}内的Class<T>
对象非常重要。 }} 方法。由于select
返回类型为newInstance
的对象,因此编译器可以执行类型检查,从而消除了强制转换。
<小时/> 1
答案 1 :(得分:8)
answer by dasblinkenlight已经证明了这个参数的一个主要用途。还有一个我认为相关的方面:使用该参数,您可以限制要在给定位置传递的类的类型。例如,
Class<? extends Number> cls
表示cls
可以是实现Number
接口的任何类。这有助于在编译时捕获某些错误,并使类参数要求更加明确。
或许与没有泛型的情况进行比较是为了
// Java ≥5 with generics // Java <5 style without generics
Class<? extends Foo> c; Class c;
Foo t1 = c.newInstance(); Foo t1 = (Foo)c.newInstance();
Object obj; Object obj;
Foo t2 = c.cast(obj); Foo t2 = (Foo)c.cast(obj);
如您所见,没有T
作为参数将需要许多显式强制转换,因为相应的方法必须返回Object
而不是T
。如果Foo
本身是泛型类型参数,那么将取消选中所有这些强制转换,从而产生一系列编译器警告。你可以压制它们,但核心问题仍然存在:除非你正确使用type参数,否则编译器无法检查这些强制转换的有效性。
答案 2 :(得分:1)
在Java中,有一个元类:Class
。它的实例(每种类型只存在一个)用于表示类和接口,因此T
中的Class<T>
指的是当前实例的类或接口的类型 Class
代表。
答案 3 :(得分:0)
在类类型中使用泛型是顶级定义类的类型。如果我有'Class obj',我的对象obj只能拥有Charsequence的子级。 这是一个可选参数。我经常把'?'如果我不需要特定类型的类,请避免来自Eclipse IDE的警告。