我正在尝试学习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)
任何人都可以帮我理解错误吗?
您应该首先了解的是,使用以下方法签名
public static <T> void print(T a, T b)
Run Code Online (Sandbox Code Playgroud)
双方T 必须是同一类型,也就是既a和b将具有相同infered类型.
那么,为什么它的工作new ArrayList<String>()和1?因为这两个参数实际上可以表示为Serializable,这是最近的常见超类型ArrayList和Integer:
所以在这种情况下,编译器会推断T为Serializable.
在第二种情况下,签名
public static <T> void print(List<T> a, T b)
Run Code Online (Sandbox Code Playgroud)
没有共同的超类型T,这将是有效的两个List<String>和Integer.这是事实,这两个String和Integer的Serializable,但由于仿制药并不多态,这是行不通的.
编辑:它没有像我提到的那样解析为Object,而是解析为Serializable.请参阅Tunaki的正确答案.
在您的第一种情况下,T解析为最具体的类型,可以引用您的参数.
而在你的榜样,它会被解析为,因为和都是子类型.ObjectSerializableArrayListIntegerObjectSerializable
但是在你的第二个例子中,你有一个List<T>参数......
现在,当你调用它时ArrayList<String>,类型T被解析为a String.它无法解析为任何其他类型,因为它不是一个超类型ArrayList<Object>ArrayList<Serializable>ArrayList<String>