Java泛型类型推断:两示例表现差异及最具体类型判定疑问
泛型类型推断差异解析
先拆解两个案例的核心约束区别:
案例1:pick(T a1, T a2)
方法定义:
static <T> T pick(T a1, T a2) { return a2; }
调用代码:
Serializable s = pick("d", new ArrayList<String>());
这个方法的两个参数都是直接的T类型,编译器只需要找一个能同时兼容两个参数的最具体超类型:
"d"是String,new ArrayList<String>是ArrayList<String>,二者的共同超类型包括Serializable、Object等。- 因为返回值要赋值给
Serializable变量,编译器会自动选择最贴合的Serializable作为T的类型,完全符合类型推断逻辑。
案例2:test(U u, List<U> list)
方法定义:
public static <U> U test(U u, List<U> list){ return u; }
调用代码:
Object f = test("Hi", new ArrayList<Integer>());
这个方法的约束要严格得多,问题出在第二个参数的泛型容器List<U>:
- Java泛型是不变的,
ArrayList<Integer>只能匹配List<Integer>,不能当成List<Object>来用(如果允许,你可以往List<Object>里加String,破坏容器的类型安全)。这就强制要求U必须是Integer,才能让List<U>和传入的ArrayList<Integer>兼容。 - 但第一个参数是
String,要求String能赋值给U,可String和Integer没有任何继承关系,完全不兼容,所以编译器直接抛出约束冲突的错误。
你想让U推断为Object是行不通的,因为List<Object>和ArrayList<Integer>类型不匹配,编译器不会违反泛型类型安全规则去做这种推断。
内容的提问来源于stack exchange,提问作者John Smith
相关产品推荐
相关产品推荐

