调用具有不同T类的print(List <T> a,T b)时发生错误

Xin*_*Xin 5 java generics

我正在尝试学习Java Generics,并找到了以下代码.

public static <T> void print(T a, T b){
    System.out.println(a);
    System.out.println(b);
}

public static void main(String[] args){
    print(new ArrayList<String>(), 1);
}
Run Code Online (Sandbox Code Playgroud)

哪个没问题.

但是,当我将print方法更改为以下内容时,它会让我编译错误.

public static <T> void print(List<T> a, T b){
    System.out.println(a);
    System.out.println(b);
}
Run Code Online (Sandbox Code Playgroud)

错误:

GenericTest.java:9: error: method print in class GenericTest cannot be applied to given types;
  print(new ArrayList<String>(), 1);
    ^
  required: List<T>,T
  found: ArrayList<String>,int
  reason: no instance(s) of type variable(s) T exist so that argument type int conforms to formal parameter type T
  where T is a type-variable:
    T extends Object declared in method <T>print(List<T>,T)
1 error
Run Code Online (Sandbox Code Playgroud)

任何人都可以帮我理解错误吗?

Tun*_*aki 8

您应该首先了解的是,使用以下方法签名

public static <T> void print(T a, T b)
Run Code Online (Sandbox Code Playgroud)

双方T 必须是同一类型,也就是既ab将具有相同infered类型.

那么,为什么它的工作new ArrayList<String>()1?因为这两个参数实际上可以表示为Serializable,这是最近的常见超类型ArrayListInteger:

  • ArrayList实现Serializable接口.
  • 1可以盒装成一个Integer,也是Serializable.

所以在这种情况下,编译器会推断TSerializable.


在第二种情况下,签名

public static <T> void print(List<T> a, T b)
Run Code Online (Sandbox Code Playgroud)

没有共同的超类型T,这将是有效的两个List<String>Integer.这是事实,这两个StringIntegerSerializable,但由于仿制药并不多态,这是行不通的.

  • @Xin,擦除与你的场景没有任何关系(在运行时是的,因为擦除它将是Object)...你的是关于推论... (2认同)

Cod*_*der 5

编辑:它没有像我提到的那样解析为Object,而是解析为Serializable.请参阅Tunaki的正确答案.

在您的第一种情况下,T解析为最具体的类型,可以引用您的参数.

而在你的榜样,它会被解析为,因为和都是子类型.Object SerializableArrayListIntegerObject Serializable

但是在你的第二个例子中,你有一个List<T>参数......

现在,当你调用它时ArrayList<String>,类型T被解析为a String.它无法解析为任何其他类型,因为它不是一个超类型ArrayList<Object> ArrayList<Serializable>ArrayList<String>