问题描述

Java8升级了泛型参数推导能力,即支持泛型方法调用表达式作为方法参数时,支持类型自动推导。

在此之前,泛型方法调用表达式作为方法参数时,编译器视其类型为Object,不支持泛型。

例如以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
@SuppressWarnings("unchecked")
public class DemoService {
private final Map<String, Object> data = new HashMap<String, Object>();

public <T> T getValue(String key) {
return (T) data.get(key);
}

public void test() {
String s = String.valueOf(getValue("k1"));
}
}

使用Java6编译器的结果:

java6

使用Java8以后,带来的问题是,如果方法有重载(例如String.valueOf),编译器可能无法推测出准确的返回值类型。

使用Java8编译器的推导结果:

java8

此类代码编译期不会报错,但是类型推导是错误的,运行时会出现java.lang.ClassCastException

解决方法

解决方法是在有重载的方法调用时,传递泛型表达式不能依赖自动类型推导,必须指定类型参数。

1
String s = String.valueOf((Object) getValue("k1"));

java8-right

参考资料:
Why does the Java 8 generic type inference pick this overload?