我不得不发现我的项目中有Java代码,它在Eclipse中编译并运行良好,但在javac中抛出编译错误。
一个独立的片段:
import java.util.HashSet;
import java.util.Set;
public class Main {
public static void main(String[] args) {
Set<Integer> setOfInts = new HashSet<Integer>();
Set<Object> setOfObjects = covariantSet(setOfInts);
}
public static <S, T extends S> Set<S> covariantSet(Set<T> set) {
return new HashSet<S>(set);
}
}
javac 中的编译返回:
Main.java:10: incompatible types
found : java.util.Set<java.lang.Integer>
required: java.util.Set<java.lang.Object>
Set<Object> setOfObjects = covariantSet(setOfInts);
^
此错误现在会阻止在 Maven 中构建项目。由于 Eclipse 编译器被构建得更加宽容,我现在必须假设上面静态方法的代码片段的定义和使用不是有效的 Java?
Sun的1.6 JDK似乎无法推断出正确的类型。以下似乎适用于我的机器:
Set<Object> setOfObjects = Main.<Object, Integer>covariantSet(setOfInts);
注意,您必须调用静态方法以类名为前缀
你是对的。这个问题确实存在。 Eclipse 不使用
javac
。它使用自己的编译器。
实际上javac是“正确的”。泛型是删除。类型
S
未包含在字节码中,因此 jvm 在运行时没有足够的有关返回类型的信息。为了解决这个问题,改变方法原型如下:
public static <S, T extends S> Set<S> covariantSet(Set<T> set, Class<S> returnType)
现在返回类型在运行时传递给方法,编译器不应该抱怨。
在 Maven 构建脚本中,您已经设置了编译器版本。
在 Ant 中它看起来像这样:
<property name="source.version" value="1.5" />
搜索 1.3 或 1.4,或编译以在 Maven 脚本中查找该值
如果值为 1.5,编译器将接受泛型(请参阅错误消息)
我知道这是个老问题,但我想提一下,该函数可以写成:
import java.util.HashSet;
import java.util.Set;
public class Main {
public static void main(String[] args) {
Set<Integer> setOfInts = new HashSet<Integer>();
Set<Object> setOfObjects = covariantSet(setOfInts);
}
public static <S> Set<S> covariantSet(Set<? extends S> set) {
return new HashSet<S>(set);
}
}
它更干净一点,您可以完全按照您的意图使用该函数(使用隐式泛型类型)。
将下一个插件添加到您的 pom.xml 中:
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>