1

I usually work with IntelliJ but recently one of my team mate opened project in eclipse and he found eclipse showing error Type mismatch: cannot convert from Object to boolean in 2 separate java files. I crossed checked in IntelliJ but no error.

Below are the screenshot from Eclipse and IntelliJ respectively:

Eclipse:

enter image description here

IntelliJ

enter image description here

I also checked that both the IDEs have same compiler compliance level, i.e. 11

Eclipse:

enter image description here

IntelliJ

enter image description here

Even though Eclipse is showing error, if I run the project in eclipse then build and run is successful.

As in above actual code example row object is created from an interface, I do not have access to see it's actual implementation. Hence just to generate the scenario so that I can understand why and how two different IDEs behave differently ? I have created below reproducible example:

IRow.java:

public interface IRow { <T> T getValue(); } 

RowImpl.java

public class RowImpl implements IRow { @SuppressWarnings("unchecked") @Override public <T> T getValue() { return (T) Boolean.TRUE; } } 

and the main.java

public class main { public static void main(String args[]) { IRow row = new RowImpl(); if(row.getValue()) //--> Eclipse shows error but IntelliJ not System.out.println("value is true"); } } 
19
  • And what was the error that it was complaining about ... ? Commented Nov 1, 2022 at 6:01
  • @StephenC Oh, forgot to mention it's Type mismatch: cannot convert from Object to boolean Commented Nov 1, 2022 at 6:01
  • 1
    It would appear that there is a difference between the IDEs' compilers. Could you please write a minimal reproducible example for this. So that we can try it out with other compilers, and check what the JLS says about it ... Commented Nov 1, 2022 at 6:07
  • 2
    PLEASE include a minimal reproducible example in the question - we have no idea how row is declared, we have no idea how T is being inferred (or not) as return value of getValue, .... Commented Nov 1, 2022 at 6:58
  • 1
    The type of row.getValue(..) depends on the generics bound determined by the compiler for whatever roq might be, which you did not include in your paste. Hence, this question cannot be answered. Intellij binds it to 'boolean', ecj evidently does not. The error is elsewhere and this clause merely triggers it, it is not itself the cause. A full reproducible example is the next step :) Commented Nov 1, 2022 at 7:03

1 Answer 1

2

Eclipse uses its own compiler, distinct from javac, and this error appears to be the manifestation of a difference in compiler implementation.

This is the ticket raised on their issue tracker. https://bugs.eclipse.org/bugs/show_bug.cgi?id=513766

Eclipse compiler devs seem to consider it a bug in javac, rather than the other way around. So perhaps the question should be "why does javac accept it"? This ticket exists for the JDK https://bugs.openjdk.org/browse/JDK-8179483, and was raised by Dan Smith who is a language designer at Oracle. He states that "javac should reject this program".

That said, I'd be quite surprised if they remove this "feature". Oracle are not in the habit of making backwards-incompatible changes, which this would be for people like you. A more likely solution seems an adjustment to the spec to allow for it, but I'd bet it's more complex than it seems on the surface, or they might have addressed it by now.

I think effectively this behaviour is ambiguously defined, and you should ideally avoid relying on it. I'd change your code to

if(Boolean.TRUE.equals(row.getValue())) 
Sign up to request clarification or add additional context in comments.

4 Comments

Oh! that's really very complex. But, according to you who is more accurate/correct eclipse or javac. After reading your answer and ticket I feel Eclipse team is correct because JLS here says that "Expression must have type boolean or Boolean, or a compile-time error occurs. " What do you think?
@Amogh That part of the spec isn't in disagreement. By declaring your method as <T> T foo(), you're stating "this can return whatever type the caller asks for", which is obviously a bit strange since it actually always returns a boolean regardless of what type the caller asks for. That logical inconsistency is what leads to you having to suppress the unchecked cast warning. But assuming your method could return whatever type the caller wanted, then it can return Boolean, which would satisfy that part of the spec.
@Amogh The problem is actually related to whether an if-statement is allowed to infer its expression to be boolean. I believe the spec doesn't say. The javac implementation does, and the Eclipse implementation does not. It seems somewhat reasonable to me, but it seems to be working by accident - by treating the expression as an assignment, which it's not.
Thanks Michael detailed explanation. I will change my code to cast the value first then use as expression.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.