为什么以下代码在没有任何警告的情况下干净地编译,即使使用xlint:all
?
class A<V> {
public V v;
public <V> A() {
}
public static <V> A<V> create() {
return new A<V>();
}
}
public class FooMain {
public static void main(String args[]) {
A.create().v = 5;
A.create().v = "a string";
}
}
运行:
javac -Xlint:all src/FooMain.java
导致编译干净而没有任何警告(未选中等)。在第一行创建的泛型类A
实例的类型参数化是什么,第二行是什么?编译器如何确定类型?通过查看r值的类型?
答案 0 :(得分:4)
在这两个语句中,编译器没有足够的信息来推断V
的类型参数。发生这种情况时,默认为V
的上限,即Object
。
分配有效,因为5
和"a string"
都可以分配给Object
。
我们可以通过尝试将其分配给更具体的类型来证明A.create().v
的类型为Object
:
Integer i = A.create().v; // Type mismatch: cannot convert from Object to Integer
错误是相同的,即使我们首先指定一个更具体的类型(赋值表达式的结果是指定变量的类型):
Integer i = (A.create().v = 5); // same error
请注意&#34;类型见证&#34;可用于显式指定泛型类型参数,如果它们没有被推断:
Integer i = A.<Integer>create().v; // valid
A.<String>create().v = 5; // incompatible types
A.<Integer>create().v = "a string"; //
这些是用于演示编译器行为的人为例子,但类型证人偶尔会有用,for example:
static void m(List<String> list) { }
public static void main(String args[]) {
m(Collections.emptyList()); // error
m(Collections.<String>emptyList()); // valid
}
答案 1 :(得分:1)
由于这两个陈述
A.create().v = 5;
A.create().v = "a string";
编译器可以通过<V>
<Integer>
,在第二种情况下<V>
由<String>