mtsz
mtsz

Reputation: 2855

Java generics compile in Eclipse, but not in javac

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?

Upvotes: 15

Views: 2780

Answers (5)

NiematojakTomasz
NiematojakTomasz

Reputation: 2473

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).

Upvotes: 0

Raffaele
Raffaele

Reputation: 20885

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

Upvotes: 12

Cesarla
Cesarla

Reputation: 1

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>

Upvotes: -1

AlexR
AlexR

Reputation: 115328

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.

Upvotes: 10

AlexWien
AlexWien

Reputation: 28727

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)

Upvotes: 0

Related Questions