注意:这不是我已经链接到下面的问题的重复。我很明显在发布前先阅读了这个问题/答案,但没有以任何形式回答我的问题。
这个链接的问题会更详细地解释泛型类存在的原因。但是,在我的情况下,我没有专门针对Class的好处给出答案。
What does the generic nature of the class Class<T> mean? What is T?
我编写了一个实用程序方法,它接受类型为Class的参数'cl',并使用cl.isInstance(objectInstance)
方法执行逻辑。
但是我见过使用通用通配符Class<?>
声明参数的示例代码。
为什么不使用没有通用通配符的Class? Class不能代表所有可能的类类型,包括泛型吗?如果在我的情况下使用Class<?>
,有什么好处?
现有相关问题(见下文)中接受的答案实际上并未提供有用的答案。
答案 0 :(得分:6)
主要区别在于读者代码的(自我)文档。声明为Class<?>
的变量表示:“此Class
实例表示的实际类型未知或在编译时无法表示,我知道”。相比之下,类型Class
说:“我不是在这里使用泛型”,或许,因为你不知道Class
是通用的,或者你有点草率,不明白Class<?>
和Class
之间的差异,或者这是非常旧的前泛型代码。
此对代码有后果。 E.g。
Class<?> unknownType=Object.class;
Class<String> string=unknownType;
当您将明确未知的类型分配给声明已知类型的变量时,会产生编译时错误。
相比之下
Class nonGenericType=Object.class;
Class<String> string=nonGenericType;
只会在执行非通用的,即未经检查的操作时生成(可抑制的)警告。
关于使用Class
对象可以做什么,除了赋值之外,没有区别,因为当你使用它创建一个新实例时,返回引用的编译时类型将是最多的两种情况下都有抽象类型java.lang.Object
。如果Class
方法接收与类型参数相关的参数,则会出现差异,因为您无法为未知类型Class<?>
调用此类方法(这与尝试插入元素的方法相同一个List<?>
),而您可以在原始Class
实例上取消选中此类方法。但由于没有这样的方法,Class<?>
和Class
之间的功能没有区别。
但是,您应该始终使用Class<?>
来确保不会发生意外的未经检查的操作,例如上面显示的分配。如果使用Class
不产生编译器警告,则应检查如何(重新)启用它们。如果编译器以静默方式忽略原始类型或未经检查的操作,则可能存在其他问题,而不是Class
以外的其他类型,隐藏在某处。
答案 1 :(得分:2)
通配符类型<?>
与此特定方案中的原始类型之间的区别仅在于编译器是否会警告您。否则它们是等价的,所以如果由于某种原因你不想使用<?>
语法并且你不关心编译器警告,你可以使用原始类型而没有任何问题。
Netbeans没有抱怨原始类型不正确的行为,我的Eclipse会在使用原始Class
时抱怨。
Class
对象具有不同的使用模式,这会影响类型是否为具体类型(在方法参数中显示为Class<T> clazz
)或通配符Class<?>
。
API中最常见的形式是具体类型,因为它允许您以类型安全的方式使用newInstance()
(主要)(使所有Class<T>
个对象自动为类型安全的工厂),如下:
public static void List<T> fill(Class<T> clazz, int size) {
List<T> l = new ArrayList<T>();
for(int i = 0;i < size; i++)
l.add(clazz.newInstance());
return l;
}
所以Class<T>
很有用,但Class<?>
呢?好吧,不是那么多。如开头所示,它只是语法合规性所必需的。另一种方法是冗余使用具体的T
类型。
public void foo(Class<?> clazz) {
// Do something non-typed, we don't have a type
}
VS
public <T> void foo(Class<T> clazz) {
// Do something non-typed, even though we have a type T
}