Java泛型编译错误

10

我有如下的通用类:

public class GenericClass<E,T extends Comparable<T>>
{
    public static <E, T extends Comparable<T>> GenericClass<E, T> create()
    {
        return new GenericClass<E, T>();
    }

    private GenericClass()
    {
    }
}

这是我简单使用它的方式:

GenericClass<MyClass, Double> set = GenericClass.create();

Eclipse编译没有出现错误,但使用ant构建时会出现以下错误:

MyClass.java:19: incompatible types; no instance(s) of type variable(s) E,T exist so that GenericClass<E,T> conforms to GenericClass<MyClass,java.lang.Double>
[javac] found   : <E,T>GenericClass<E,T>
[javac] required: GenericClass<MyClass,java.lang.Double>
[javac]             GenericClass<MyClass, Double> set = GenericClass.create();

谢谢!


SortedSetByDoubleValue 是什么? - Jon Skeet
已修复...我为简单起见更改了类名。 - duduamar
我的建议是在静态方法create和类中不要使用相同的泛型类型名称。虽然从技术上讲是合法的,但可能会导致一些难以发现的错误。我强烈建议在整个create()定义中将E、T替换为E2和T2(或其他名称)。 - Grzegorz Oledzki
为了最好地使用子类,边界应该是 T extends Comparable<? super T> - newacct
2个回答

8
尝试使用这个:
      GenericClass<String, Double> set = GenericClass.<String,Double>create();

Eclipse编译器和javac在容错性方面存在差异。


1
那么谷歌的Sets.newHashSet()(例如)是如何工作的呢?有什么区别吗? - duduamar
@duduamar:newHashSet() 更简单:它对两个类型参数没有限制。 - Joachim Sauer

0

你的表达式 GenericClass.create() 没有明确指定类型,因此编译器无法推断出 E 和 T 的真实类型。你需要改变函数的原型来帮助编译器。

最简单的方法是传递类。

示例:

public class GenericClass<E,T extends Comparable<T>> {
    public static <E, T extends Comparable<T>> GenericClass<E, T> create(Class<E> e, Class<T> t) {
        return new GenericClass<E, T>();
    }

    private GenericClass() {
    }
}

GenericClass<MyClass, Double> set = GenericClass.create(MyClass.class, Double.class);

编译器应该能够推断类型。这是可能的(正如Eclipse编译器清楚地展示的那样)。我发现了类似的错误,其中javac无法推断类型,而Eclipse编译器可以。每次我都为此提交了错误报告(同时向Eclipse和Sun/Oracle提交),结果证明是javac的问题。 - Joachim Sauer
是的...但javac是参考;-) 无论如何,多亏了Grzegorz,我学到了新东西。 - cadrian

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