为什么这个编译没有任何未经检查的类型警告?

Mar*_*tus 9 java generics

为什么以下代码干净地编译而没有任何警告,即使是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";
    }
}
Run Code Online (Sandbox Code Playgroud)

运行:

javac -Xlint:all src/FooMain.java
Run Code Online (Sandbox Code Playgroud)

导致干净的编译没有任何警告(未选中等).A在第一行创建的泛型类实例的类型参数化是什么,第二行是什么?编译器如何确定类型?通过查看r值的类型?

Pau*_*ora 4

在这两个语句中,编译器没有足够的信息来推断 的类型参数V。当发生这种情况时,它默认为V的上限,即Object。

这些分配是有效的,因为 和 都可5分配"a string"给Object。

A.create().v我们可以通过尝试将isObject分配给更具体的类型来显示 is 的类型:

Integer i = A.create().v; // Type mismatch: cannot convert from Object to Integer
Run Code Online (Sandbox Code Playgroud)

即使我们先分配一个更具体的类型(赋值表达式的结果是分配变量的类型),错误也是一样的:

Integer i = (A.create().v = 5); // same error
Run Code Online (Sandbox Code Playgroud)

请注意,“类型见证”可用于显式指定泛型类型参数(如果未推断出它们):

Integer i = A.<Integer>create().v; // valid

A.<String>create().v = 5;           // incompatible types
A.<Integer>create().v = "a string"; //
Run Code Online (Sandbox Code Playgroud)

这些是为了演示编译器行为而设计的示例,但类型见证有时很有用,例如:

static void m(List<String> list) { }

public static void main(String args[]) {

    m(Collections.emptyList());         // error
    m(Collections.<String>emptyList()); // valid
}
Run Code Online (Sandbox Code Playgroud)