Eclipse编译器或javac中的错误(“无法确定T的类型参数”)

74
以下代码:
public class GenericsTest2 {

    public static void main(String[] args) throws Exception {
        Integer i = readObject(args[0]);
        System.out.println(i);
    }

    public static <T> T readObject(String file) throws Exception {
        return readObject(new ObjectInputStream(new FileInputStream(file)));
        // closing the stream in finally removed to get a small example
    }

    @SuppressWarnings("unchecked")
    public static <T> T readObject(ObjectInputStream stream) throws Exception {
        return (T)stream.readObject();
    }
}

在Eclipse中编译正常,但使用javac编译时出现错误(无法确定类型参数T;不存在满足类型变量T上限T、java.lang.Object的唯一最大实例)。

当我将readObject(String file)更改为

    @SuppressWarnings("unchecked")
    public static <T> T readObject(String file) throws Exception {
        return (T)readObject(new ObjectInputStream(new FileInputStream(file)));
    }

代码可以在Eclipse和通过Javac编译器编译。哪个是正确的,Eclipse编译器还是Javac编译器?

5个回答

66
我觉得这是Sun编译器的一个错误,可以在这里这里报告中找到相关信息。因为如果你将代码改成下面这样,两个编译器都能正常工作,这似乎与错误报告中描述的情况完全一致。
return GenericsTest2.<T>readObject(new ObjectInputStream(new FileInputStream(file)));

13
在这种情况下,我认为您的代码是错误的(而Sun编译器是正确的)。您的输入参数中没有任何内容可以推断出类型T的实际值。在这种情况下,最好让它返回Object,并让客户端手动转换结果类型。这样应该能够运行(尽管我没有测试过):
public static <T> T readObject(String file) throws Exception {
    return GenericsTest2.<T>readObject(new ObjectInputStream(new FileInputStream(file)));
}

1
返回 GenericsTest2.<T>readObject(new ObjectInputStream(new FileInputStream(file))); 是有效的。谢谢! - Tobias Schulte
1
我不同意,它看起来更像下面相关的错误。编译器应该信任显式转换而不需要类型推断 - 以下代码可以成功编译@SuppressWarnings("unchecked") public static T createT(String className) throws Exception { return (T) Class.forName(className).newInstance(); } - Duncan McGregor

3
Oracle JDK6 u22应该是正确的,但我也在JDK6 u24上遇到了这个问题。
这是eclipse的一个bug(bug 98379)。
这个问题没有被修复,但可以通过解决方法来解决,例如在eclipse bugs中的示例(请参见链接)。

1
我发现这个问题出现在Java版本“1.6.0_22”中。当我升级到Java版本“1.6.0_32”时,它消失了,因为在更新25中已经修复了该问题。

0
如果您可以修改readObject方法,使其在被调用时能够透明地工作,那么您也可以使用以下方法:
public static <T> T readObject(String file, Class<T> type) throws Exception {
    return type.cast(readObject(new ObjectInputStream(new FileInputStream(file))));
}

通过这种方式,调用者被强制指定结果的类型,编译器也知道如何转换结果。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接