如果我将一个类声明为一个字段:
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!)
始终使用非原始形式,即使您必须使用 ?
因为您无法知道类型参数是什么(或受其限制),所以与使用原始类型相比,您允许编译器更全面地推断程序的正确性。
为什么要有原始类型?
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/