使用Class <! - ? - >而不是Class作为方法参数类型有什么好处?

时间:2016-02-29 06:59:54

标签: java class reflection

注意:这不是我已经链接到下面的问题的重复。我很明显在发布前先阅读了这个问题/答案,但没有以任何形式回答我的问题。

这个链接的问题会更详细地解释泛型类存在的原因。但是,在我的情况下,我没有专门针对Class的好处给出答案。

What does the generic nature of the class Class<T> mean? What is T?

我编写了一个实用程序方法,它接受类型为Class的参数'cl',并使用cl.isInstance(objectInstance)方法执行逻辑。

但是我见过使用通用通配符Class<?>声明参数的示例代码。

为什么不使用没有通用通配符的Class? Class不能代表所有可能的类类型,包括泛型吗?如果在我的情况下使用Class<?>,有什么好处?

现有相关问题(见下文)中接受的答案实际上并未提供有用的答案。

What does Class<?> mean in Java?

2 个答案:

答案 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
}