为什么编译器的行为如此?

时间:2017-01-13 12:38:59

标签: java generics type-inference

看,我们来了代码:

public class Test2 {
    public static void main(String... args) {
        ArrayList<Exception> a = new ArrayListFactory().create(new RuntimeException());
        ArrayList<Exception> b = new ArrayListFactory().create("Z");
        }
}

class ArrayListFactory {
    public <T> ArrayList<T> create(T example) {
        return new ArrayList<T>(10);
    }
}

和第二个语句的编译错误:

Error:(15, 63) java: incompatible types: inference variable T has incompatible bounds
    equality constraints: java.lang.Exception
    lower bounds: java.lang.String
  1. 实际上,第一个语句分配给ArrayList<Exception>另一个ArrayList<RuntimeException>,它是否与java规则发生冲突?
  2. 第二个语句推断Exception的{​​{1}}类型参数。它是否检查方法的返回类型是否与它在ArrayListFactory类中定义的参数类型相匹配?似乎这个方法调用应该动态解决,为什么编译器确定它正在处理正确的方法?

3 个答案:

答案 0 :(得分:0)

所有Generic类型都将在编译时分配,因此编译器将从您的赋值中推断出类型,并且它预期两者都是相同的,但在您的情况下它是不同的,因此它将给出类型不匹配错误,更改此类代码以修复错误

public class Test2 {

    public static void main(String... args) {
        ArrayList<RuntimeException> a = new ArrayListFactory().create(new RuntimeException());
        ArrayList<String> b = new ArrayListFactory().create("Z");  
        }
}

答案 1 :(得分:0)

在此声明中:

ArrayList<Exception> b = new ArrayListFactory().create("Z");

编译器使用类型推断(来自声明ArrayList<Exception>)在create()的泛型返回类型上添加约束。它被称为目标类型。表达式的目标类型是Java编译器所期望的数据类型,具体取决于表达式的显示位置。

在这种情况下,T应该是Exception的子类。 RuntimeException因此很好;但是String不是。

此功能随Java 8一起出现。有关它的更多信息:http://docs.oracle.com/javase/8/docs/technotes/guides/language/enhancements.html

答案 2 :(得分:0)

1)先致电

    ArrayList<Exception> a = new ArrayList<RuntimeException>();

不是Java中泛型的合法用法。 您可以前往https://github.com/reactjs/react-redux/blob/master/docs/api.md#provider-store了解。

2)第二次电话

T类型的推断取决于从调用者声明的返回类型。

此处调用者将返回的类型声明为Exception

 ArrayList<Exception> b = new ArrayListFactory().create("Z");

编译错误:

  

错误:(15,63)java:不兼容的类型:推理变量T有   不相容

     

边界       等式约束:java.lang.Exception

传递字符串:

 ArrayList<String> b = new ArrayListFactory().create("Z");