【问题标题】:What is the benefit of using Class<?> instead of Class as a method parameter type?使用 Class<?> 而不是 Class 作为方法参数类型有什么好处?
【发布时间】:2016-02-29 06:59:54
【问题描述】:

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

这个链接的问题确实更详细地解释了为什么泛型类存在。但是,在我的情况下,我没有得到关于 Class 的好处的具体答案。

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

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

但是,我看到了使用通用通配符 Class&lt;?&gt; 声明参数的示例代码。

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

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

What does Class<?> mean in Java?

【问题讨论】:

  • 接受的答案完美地描述了这种情况。如果你对此不满意,那是不幸的。 “好处”是您将编写语法正确的代码并且不会收到警告。
  • 不,没有!请阅读已接受问题下的 cmets。我的问题是使用 Class> 而不是 Class 有什么好处。我正在努力学习这一点。我正在从具有 System.Type 类但没有 System.Type 的 .NET 迁移到 Java。这是一个完全合理的问题。投票重新开放。
  • 我告诉过你没有任何好处。这是语法要求,因为Class 是通用的。我没有说这不是一个合理的问题,我只是说答案已经有效。 .NET 没有 System.Type&lt;&gt; 的事实无关紧要。
  • Netbeans 8.1 在我使用 Class cl 作为参数的地方没有给出警告,所以这甚至不正确。我没有关闭任何警告。
  • 好吧,我的 Eclipse 在使用 Class 时正确地警告原始类型,所以无论如何你都错了。

标签: java class reflection


【解决方案1】:

主要区别在于向读者提供的代码(自我)文档。声明为Class&lt;?&gt; 的变量表示:“此Class 实例表示的实际类型在编译时未知或不可表示,我知道这一点”。相比之下Class这个类型说:“我这里没有用泛型”,可能是因为你不知道Class是泛型的,或者你有点马虎,没看懂@987654325的区别@ 和 Class,或者这是非常古老的预泛型代码。

对代码有的影响。例如

Class<?> unknownType=Object.class;
Class<String> string=unknownType;

将显式未知类型分配给声明已知类型的变量时会产生编译时错误。

对比

Class nonGenericType=Object.class;
Class<String> string=nonGenericType;

只会在您执行非通用(即未检查)操作时产生(可抑制的)警告。

关于你可以用Class 对象做什么,除了赋值之外,没有区别,因为当你使用它创建一个新实例时,返回的引用的编译时类型将是最抽象的类型在这两种情况下都有java.lang.Object。如果 Class 方法接收与类型参数相关的参数,则会出现差异,因为您不能为未知类型调用此类方法,Class&lt;?&gt;(这与尝试将元素插入 List&lt;?&gt; 相同) ) 虽然您可以在原始 Class 实例上调用此类未选中的方法。但是由于没有这样的方法,所以Class&lt;?&gt;Class在功能上没有区别。

不过,您应该始终使用Class&lt;?&gt; 以确保不会发生意外的未经检查的操作,例如上面显示的分配。如果使用Class 不会产生编译器警告,您应该检查如何(重新)启用它们。如果编译器默默地忽略原始类型或未经检查的操作,则可能存在其他问题,Class 以外的其他类型隐藏在某个地方。

【讨论】:

  • +1。回复:“当你用它来创建一个新实例时,你会得到最抽象的类型,java.lang.Object”:我读了几遍才明白这个说法——起初我以为你说的是​​新的instance 不会是任何更具体的类的实例(由于某种 X-treme Erasure™)。不过,我没有关于如何使其更清晰的具体建议。 :-/
  • @Holger,感谢您的解释。似乎如果 Java 有真正的泛型(即在字节码级别),它将消除这种令人困惑的(对于新手来说)Class 是泛型的期望。例如,.NET 中的 System.Type 是 java.lang.Class 的直接等价物,它是原始(非泛型)类型。没有合理的理由让它是通用的。毕竟 System.Type 和 java.lang.Class 的主要目的是作为描述另一个类的“元对象”。 .NET 远非完美,但至少他们在泛型方面做得对。再次感谢。
【解决方案2】:

通配符类型&lt;?&gt;this 特定场景中的原始类型之间的区别仅在于编译器是否会警告您。否则它们是等价的,所以如果由于某种原因你不想使用&lt;?&gt; 语法并且你不关心编译器警告,你可以使用原始类型而不任何问题。

Netbeans 不抱怨原始类型是不正确的行为,我的 Eclipse 在使用原始 Class 时会抱怨。

Class 对象具有不同的使用模式,这会影响该类型是具体类型(在方法参数中显示为Class&lt;T&gt; clazz)还是通配符Class&lt;?&gt;

API 中最常见的形式是具体类型,因为它允许您(主要)以类型安全的方式使用newInstance()(使所有Class&lt;T&gt; 对象自动成为类型安全的工厂),例如以下:

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&lt;T&gt; 很有用,但是Class&lt;?&gt; 呢?好吧,没有那么多。如开头所述,它只是语法合规性所必需的。另一种方法是冗余地使用具体的T 类型。

public void foo(Class<?> clazz) {
    // Do something non-typed, we don't have a type
}

对比

public <T> void foo(Class<T> clazz) {
    // Do something non-typed, even though we have a type T
}

【讨论】:

  • 谢谢。您如何看待这个问题:9406025 作为重复项?它似乎更广泛,但与我的要求更相关。我不介意是否真的存在重复的问题,我只是想了解一些事情。
  • 在那个问题中,他说的是Class,而不是Class>,即更笼统地说。我问的更具体的是 Class> 但这个问题解释了为什么要引入 Class
猜你喜欢
  • 2018-01-04
  • 2011-11-24
  • 2011-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-27
  • 2020-07-01
相关资源
最近更新 更多