No,
原始类型并不像它们被参数化一样Object
,它们也不像通配符类型(<?>
).
对于原始类型,泛型是关掉.
此代码已编译(带有警告):
Cat c1 = new Cat<String>();
Cat<Integer> c2 = c1;
这段代码没有:
Cat<? extends Object> c1 = new Cat<String>(); // btw: this is the same as Cat<?>
Cat<Integer> c2 = c1; // error
这也不:
Cat<Object> c1 = new Cat();
Cat<Integer> c2 = c1; // error
至于类型var
:
编译后字段的类型是参数的上限(Object
如果没有指定)。但是如果我们访问编译器会做什么var
?
Cat<String> c1 = ...
String c1Var = c1.var;
这段代码编译没有错误,但编译器实际编译的是:
Cat c1 = ...
String c1Var = (String) c1.var;
如你看到的,var
始终被视为类型字段Object
, but 对于泛型,编译器会自动插入类型安全的强制转换. 就这样。如果你使用原始类型,你必须自己做。不管怎样,当你把一个Cat
将一个整数存储在a中Cat<String>
变量,如果您尝试读取,您只会得到运行时异常var
.
A quiz
现在看一下声明集合.max http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/java/util/Collections.java#Collections.max%28java.util.Collection%29。为什么你认为参数定义为T extends Object & Comparable<? super T>
?
答案编码为rot13 http://rot13.com:
Fb 贡 nsgre pbzcvyngvba 古尔盖亚 glcr vfBowrpg
, abg Pbzcnenoyr
。 Guvf vf arrqrq sbe onpxjneqf pbzcngvovyvgl (gur zrgubq vgfrys vf byqreguna trarevpf)。
Edit:
这是我刚刚偶然发现的另一个很好的例子:
class Foo<T> {
public <V> V bar(V v) { return v; }
}
//compiles
Foo<Object> foo = new Foo<Object>();
Integer i = foo.bar(1);
//compiles
Foo<?> foo = new Foo<String>();
Integer i = foo.bar(1);
// fails
Foo foo = new Foo();
Integer i = foo.bar(1); // error: Object cannot be converted to Integer
不使用参数会完全禁用泛型。