Dana
Dana

Reputation: 2739

Java generics code compiles in eclipse but not in command line

I know there have been several questions in the past regarding things that compile in eclipse but not in command line, but I could not find an answer to my problem yet.

In particular, I think that I was able to set eclipse to use my system compiler, but that still did not solve the problem.

I am currently checking under : 'Preferences -> Java -> Installed JREs'.

This contains only one JRE which is my system one.

Here are the specifics of the problem

I have a java generic class that takes as argument an Enum type, like so:

public class MyClass<T extends Enum<T>>

Somewhere inside the class I compare a known enum value with values of T. So for example let's assume I have this enum:

public enum OtherEnum{
 a,
 b
}

And then I test:

protected void foo(T enumVal){
    if(enumVal == OtherEnum.a){
        // do something
    }
    else if(enumVal == OtherEnum.b){
        // do something else
    }
}

This compiles with no problem in eclipse but in command line javac I get this error:

incomparable types: T and OtherEnum

I tried this on two systems that use variant of java 1.6 (1.6.0_26 and 1.6.0_16). One is a Mac, the other a linux. They both give the same error, while eclipse is compiling away with no problem.

So:

  1. How do I make sure which compiler eclipse is using?

  2. What is even the problem here?

Thanks!

Upvotes: 3

Views: 1448

Answers (4)

maurizio
maurizio

Reputation: 51

This is a javac bug that has been fixed in JDK 7.

See https://bugs.java.com/bugdatabase/view_bug?bug_id=6548436

Upvotes: 5

irreputable
irreputable

Reputation: 45433

Very interesting question.

The following code doesn't compile

    Integer x = null;
    String s = null;
    if(x==s){}   // error: incomparable types

JLS3#15.21.3 [1] says

A compile-time error occurs if it is impossible to convert the type of either operand to the type of the other by a casting conversion (§5.5)

Apparently the previous example looks like an obvious programming error, so the spec tries to catch it and alert the programmer. There wouldn't have been any trouble is Java wanted to allow it. The workaround for the example is to cast one side to Object.

Back to your question, we need to decide if OtherEnum can be cast to T, or the other way around. This is a surprisingly difficult question; following the procedure of JLS3#5.5 [2], the answer is no.

It comes down to whether OtherEnum can be cast to Enum<T>; then we can find super types X=Enum<OtherEnum> and Y=Enum<T>, which are provably distinct parameterized types. So cast is illegal.

Well, such specification is too elaborate, who in their right minds would care?

You can work around it by casting one to Object, say (Object)enumVal == OtherEnum.a

Java 7 behaves differently, it does compile your code. I don't know the reason. It's possible that Java7 introduces a new bug. Or it has a new spec that allows the code (but we don't have access to the new spec). Another possibility is that I misunderstood the term "provably distinct parameterized types"; however without formal definition, it is intuitive that Enum<OtherEnum> and Enum<T> are distinct.

ref

[1] http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.21.3

[2] http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#20232

Upvotes: 1

apesa
apesa

Reputation: 12443

Separate compilers...The use of == forces a stricter compile time check, therefore in the CL it is enforcing type comparison and erroring. In Eclipse you can manage the settings for the compile time and loosen the restrictions so to speak.

You can try Enum.equals() and it may not enforce such strict compile time type comparison. just a thought.

Upvotes: 0

aleroot
aleroot

Reputation: 72636

Eclipse use it's own java compiler implementation(ECJ) that have nothing to do with javac .

Eclipse Compiler for Java :

An incremental Java compiler. Implemented as an Eclipse builder, it is based on technology evolved from VisualAge for Java compiler. In particular, it allows to run and debug code which still contains unresolved errors.

Upvotes: 0

Related Questions