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.
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?
Joined: Oct 12, 2000
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.