java - 为什么 Class<?> 优于 Class

标签 java generics raw-types

如果我将一个类声明为一个字段:

Class fooClass;

Eclipse 给了我警告:

Class is a raw type. References to generic type Class should be parametrized

这在实践中意味着什么?为什么我要这样做?如果我向 Eclipse 询问“快速修复”,它会给我:

Class<?> fooClass;

这似乎没有增加太多值(value),但不再发出警告。

编辑:为什么 Class 是泛型的?您能否举一个参数化的示例,即是否可以有效使用 <?> 以外的其他内容? ?

编辑:哇!我还没有意识到这其中的深度。我还看过 Java Puzzler,它肯定让我对捕熊陷阱感到害怕。所以我会一直使用

Class<MyString> myStringClass = MyString.class;

而不是

Class myStringClass = MyString.class;

(但是从第一天开始就使用 Java,我并没有真正注意到 Class 何时变为泛型);

注意:我接受了@oxbow_lakes,因为这对我来说很有意义,但这显然是一个非常复杂的领域。我会敦促所有程序员使用特定的 Class<MyString>而不是 Class .和Class<?>Class 安全得多.

最佳答案

原始类型和无界通配符

之前的答案都没有真正解决您为什么应该更喜欢 Class<?>超过 Class ,从表面上看,前者似乎没有提供比后者更多的信息。

原因是,原始类型,即Class , 阻止编译器进行泛型类型检查。也就是说,如果您使用原始类型,颠覆类型系统。例如:

public void foo(Class<String> c) { System.out.println(c); }

可以这样调用(它会编译运行):

Class r = Integer.class
foo(r); //THIS IS OK (BUT SHOULDN'T BE)

但不是:

Class<?> w = Integer.class
foo(w); //WILL NOT COMPILE (RIGHTLY SO!)

始终使用非原始形式,即使您必须使用 ?因为您无法知道类型参数是什么(或受其限制),所以与使用原始类型相比,您允许编译器更全面地推断程序的正确性。


为什么要有原始类型?

Java Language Specification说:

The use of raw types is allowed only as a concession to compatibility of legacy code

您应该始终避免使用它们。无界通配符 ?可能在其他地方得到了最好的描述,但本质上意味着“这是在某种类型上参数化的,但我不知道(或关心)它是什么”。这与 原始类型 不同,后者是可憎的,并且在其他具有泛型的语言中不存在,例如 Scala .


为什么类参数化?

嗯,这是一个用例。假设我有一些服务接口(interface):

public interface FooService

我想注入(inject)它的实现,使用系统属性来定义要使用的类。

Class<?> c = Class.forName(System.getProperty("foo.service"));

此时我不知道我的类(class)是否属于正确的类型:

//next line throws ClassCastException if c is not of a compatible type
Class<? extends FooService> f = c.asSubclass(FooService.class); 

现在我可以实例化一个 FooService :

FooService s = f.newInstance(); //no cast

关于java - 为什么 Class<?> 优于 Class,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4337313/

相关文章:

java - 什么是原始类型,为什么我们不应该使用它呢?

Java 泛型——原始类型和参数化类型转换

java - 是什么导致了这个 ArrayIndexOutOfBoundsException?

java - 以特定的时间间隔调用java程序

java - 递归打印出数组中等于给定总和的所有子集,不会跳转到下一次迭代

java - JAMA 没有计算正确的特征向量

Swift:从泛型调用非泛型函数?

c# - C# 中更复杂的扩展泛型

java - Java 中的泛型解释了应该接受任何类型的 vector 方法

java - 什么是原始类型,为什么我们不应该使用它呢?