2012年6月17日

泛型返回值自动装箱导致javac编译报错的问题

public class A {
    private Map<String, Object> paras = new HashMap<String, Object>();
    public <T> T get(String key) {
        Object obj = paras.get(key);
        if (obj == null) {
            return null;
        }
        return (T) obj;
    }

    public void test() {
        long value1 = get("akey");
        int value2 = get("bkey");
    }
}

上面这个类,在Eclipse中是可以正确编译的,但是使用javac编译就会报以下错误:

A.java:14: 无法确定 T 的类型参数;对于上限为 long,java.lang.Object 的类型变量 T,不存在唯一最大实例 long value1 = get("akey");
A.java:15: 无法确定 T 的类型参数;对于上限为 int,java.lang.Object 的类型变量 T,不存在唯一最大实例 int value2 = get("bkey");

这是因为eclipse和jdk使用的编译器不一样,eclipse使用jdt,jdk使用的是javac。

根据报错信息,get方法并无错误,问题是出在调用的代码上。方法的返回值赋给了原子类型(long,int),这时候会用到自动装箱功能,应该是javac在处理泛型返回值自动装箱的时候遇到了问题。

看来javac在这里的检查比jdt更加严格。

我们只要把调用的代码改成不要让java自动装箱,就可以通过编译了:

Long value1 = get("akey");
Integer value2 = get("bkey");