首先创建一些代码(Java 7)来说明我的问题。
import java.util.*;
class Generics101 {
public static void addTrue(List list) {
list.add(true);
}
public static void main(String[] args) {
List<Integer> testList = new ArrayList<>();
addTrue(testList);
System.out.println(testList.get(0));
// testList.add(true); // will not compile when uncommented
}
}
我有以下两个问题:
在addTrue
方法中,Eclipse提示它不喜欢raw types
。当我尝试更改方法参数以使用通配符List<?> list
时,它将无法编译。我查看Generics Tutorial但找不到答案。我在这里想念的是什么,我应该在哪里阅读它?
相同的tutorial声明“泛型被引入Java语言以在编译时提供更严格的类型检查... ”我理解由于{{1这样的强制执行不能在运行时发生,所以我的上面的代码编译并运行。如果注释行被取消注释,它将触发编译错误,因此我假设type erasure
在同一方法中有效。这种执法的确切范围是什么?它是如何正式定义的?
答案 0 :(得分:3)
当我尝试更改方法参数以使用通配符列表列表时,它将无法编译。
它无法编译,因为您无法在List<?>
中添加任何内容。因为您不知道实际上会出现List
的类型。例如,仅限您当前的案例。您正在通过List<Integer>
。它将成功传递给List<?>
。没有问题。但您要为其添加true
,boolean
类型。如果编译器允许,它将在运行时抛出ClassCastException
。所以,这是不允许的。
因此我假设在同一方法中有更严格的类型检查。这种执法的确切范围是什么?
不,不是那样的。并不是类型检查是在某个范围内完成的。只要使用泛型,它就会被强制执行。如果与正确的泛型一起使用,您当前的代码将无法编译,因为您尝试将boolean
类型添加到List<Integer>
。你为什么期望这样做?
尝试将您的方法更改为通用方法,您将看到它无法编译:
public static <T> void addTrue(List<T> list) {
list.add(true); // Won't compile
}
我查看了Generics Tutorial但找不到答案。我在这里错过了什么,我应该在哪里阅读它?
嗯,这是Oracle的标准教程。这就是你应该阅读的地方。除此之外,您还可以在Java Generics FAQs - Angelika Langer.
上查看关于泛型的非常好的教程集