I had to discover I have Java code in my project, which compiles and runs fine in Eclipse, but throws a compilation error in javac.
A self-contained snippet:
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);
}
}
Compilation in javac returns:
Main.java:10: incompatible types
found : java.util.Set<java.lang.Integer>
required: java.util.Set<java.lang.Object>
Set<Object> setOfObjects = covariantSet(setOfInts);
^
This error now prevents building the project in Maven. As the Eclipse compiler is built to be more tolerant, I now have to assume the definition and usage of snippets as above static method is no valid Java?
It seems that Sun's 1.6 JDK can't infer the correct type. The following seems to work on my machine:
Set<Object> setOfObjects = Main.<Object, Integer>covariantSet(setOfInts);
Note that you must invoke the static method prefixed with the class name
You are right. This problem indeed exists. Eclipse does not use javac
. It uses its own compiler.
Actually javac is "right". Generics are erasures. Type S
is not included into your byte code, so jvm does not have enough information about the return type at runtime. To solve the problem change the method prototype as following:
public static <S, T extends S> Set<S> covariantSet(Set<T> set, Class<S> returnType)
Now the return type is passed to the method at runtime and compiler should not complain.
In your Maven build skript you have set the compiler version.
In Ant it lookes like this:
<property name="source.version" value="1.5" />
search for 1.3 or 1.4, or compile to find that value in the maven skripts
With value 1.5 the compiler will accept the generics (see your error messages)
I know it's old question, but I want to mention, the function could be written as:
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);
}
}
It's a little bit cleaner and you can use the function exactly how you intented to(with implicit generic typing).
Add the next plugin to your pom.xml:
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
来源:https://stackoverflow.com/questions/13533880/java-generics-compile-in-eclipse-but-not-in-javac