原始类型总是不好?
问题描述:
项目23(不要使用新代码的原始类型)有效的Java中声称,在Java代码中使用原始类型总是危险原始类型总是不好?
例如,它声称,下面的方法是危险和不安全
// Use of raw type for unknown element type - don't do this!
static int numElementsInCommon(Set s1, Set s2) {
int result = 0;
for (Object o1 : s1)
if (s2.contains(o1))
result++;
return result;
}
尽管我可以看到在s1和s2上执行任何类型的写操作或类转换操作都会导致各种异常,但我不明白为什么上述方法不安全。作者Joshua Bloch继续推荐以下方法。
// Unbounded wildcard type - typesafe and flexible
static int numElementsInCommon(Set<?> s1, Set<?> s2){
int result = 0;
for (Object o1 : s1)
if (s2.contains(o1))
result++;
return result;
}
换句话说,如果一个方法只使用Object.Class的方法和没有做任何修改所传递的参数,为什么这样做不好?
答
从某种意义上说,它阻止编译器对类型检查代码进行类型检查是不好的。
当然,你可以在没有它的情况下编写出好而安全的代码。人们每天都用Perl和Javascript来做。即使在Java中,使用原始类型和在运行时使用类型集合也没有区别。但是为了尽可能多地进行编译器检查,有一点可以说。
因此,采用类似于您的示例的方法,请使用通配符类型(Set<?>
)而不是原始类型。这样,如果你确实写了“危险”代码,如s1.addAll(s2);
,编译器会向你大喊。
在很久以前,在泛型之前,人们会在当天的集合中混合**类型(即'Hashtable'和'Vector',它们不是那些日子里的集合)。这导致了诸如'[0,“abc”,Date]'这样的事情,因为Java允许你创建自己的数据类型。使用'Set >',您可以保证一致的元素类型。 –
当然。我的问题是,原始类型不安全的情况下,只读方法或操作只涉及暴露的方法** Object.Class ** –
不,它们不是。在运行时,所有类型都是原始的,并且它们与推荐的通配符方法完全相同。但是这种方法会让编译器检查你实际上没有做这些“安全的事情”。如果没有通配符,如果您不小心将其添加到您的套件中,则不会收到错误消息。因此,如果您知道它,请使用通用类型;如果不知道,请使用通配符。不要使用原始类型。 – Thilo