• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Tiger issue with conditional expressions

 
Ranch Hand
Posts: 1272
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
This compiles and runs with jdk 1.5.0:


This code gives compiler error:
Test9.java [7:1] inconvertible types
found : java.lang.Object&java.io.Serializable&java.lang.Comparable<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<?>>
required: java.lang.String
System.out.println( (a > b ? 4.0 : true) instanceof String);


Can anyone explain it?

Is this a compiler bug?

Which result is correct?
 
Ranch Hand
Posts: 5093
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
System.out.println( (a > b ? 4.0 : true) instanceof String);

the problem is that the conditional expression cannot be used like this.
Both return values MUST be of the same type (or resolve to the same type, one can be a subclass or subinterface of another).
 
Mike Gershman
Ranch Hand
Posts: 1272
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
So why does

(a > b ? 4.0 : true) instanceof Object

compile and run correctly with the identical conditional expression?
 
author and iconoclast
Posts: 24207
46
Mac OS X Eclipse IDE Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Wow. Well, I can explain this, but I'm not happy to see it. The explanation, clearly, is autoboxing. In pre-Tiger Java, both expressions are errors, because, as Jeroen says, both branches of the conditional have to have the same type.

But under Tiger, we have autoboxing. The compiler knows that both expressions can be promoted to Objects by autoboxing, so the first expression works. The second one doesn't because if you box '4.0' you get a Double, and if you box 'true' you get a Boolean, and neither of these is a String.

I think this is terrible, because it seems so arbitrary. You and I both know you can trivially make a String out of a double and a boolean with String constructors or String.valueOf() methods, or calling toString() on the Double and the Boolean, and it intuitively feels like the compiler ought to just do it for you. But of course, that's not how autoboxing works -- the compiler knows how to turn a boolean into a Boolean, and nothing else.
 
Mike Gershman
Ranch Hand
Posts: 1272
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks, Ernest, I didn't think about autoboxing.

I still don't see how the second argument of instanceof can affect the type checking of the arguments of ? :

In any compiler design I know of, the type checking at a node of a parse tree is completed and the resulting type is passed up to the parent node before the compiler looks at the type of the next child of the parent node.

What would the grammar look like where the validity of a conditional expression depends on the other argument of the binary operator above the expression?
 
Jeroen Wenting
Ranch Hand
Posts: 5093
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
what happens is that the conditional will attempt to return whatever it's compared with.
As both Boolean and Double can be cast to Object there's no problem if you try that, but they cannot be cast to String so you get an error.

It's one of the (maybe unforeseen) consequences of autoboxing that the case with Object now works when it used to give a compiler error pre-Tiger.
In my opinion no autoboxing should take place here at all, or at worst it should always cast to Object only in this specific case.
Simply put, the conditional in this case is expected to return an Object because instanceof works on Objects. Apparently the compiler doesn't work like that though and tries to get the conditional to return the exact type you mention on the righthand side of the instanceof which is indeed a bit weird.
 
reply
    Bookmark Topic Watch Topic
  • New Topic