3

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!

Dana
  • 2,619
  • 5
  • 31
  • 45

4 Answers4

5

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

See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6548436

maurizio
  • 51
  • 1
  • This should be the accepted answer since using JDK 7+ to compile enables to compile without any error while using JDK 6 fails. Without having to change the source level compliance. – Valentin May 03 '16 at 15:49
1

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

irreputable
  • 44,725
  • 9
  • 65
  • 93
0

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.

aleroot
  • 71,077
  • 30
  • 176
  • 213
  • Wow, I didn't realize this. It's very interesting, because I have used this particular segment of my code through eclipse, so something must be working there. And I'm still not sure what created the error in the first place. – Dana Nov 10 '11 at 22:55
0

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.

apesa
  • 12,163
  • 6
  • 38
  • 43
  • That worked! I still don't understand though, why is the original version not working? Both parts of the == are defined to be Enums so why does the type-checking fail? – Dana Nov 10 '11 at 23:00
  • Because your comparing String "Content" its value, as opposed to String "Identity" its address in memory. make sense – apesa Nov 10 '11 at 23:07
  • In the case of Enums, shouldn't the identity be the same? – Dana Nov 10 '11 at 23:11
  • with the == operand your comparing the equality of the contents of EnumVal. The CL Compiler is complaining that your EnumVal is of an incomparable type. I suspect if you use stricter typecasting of EnumVal it may not error in compile time. – apesa Nov 10 '11 at 23:21