views:

203

answers:

2

Hi,

Can someone explain why this code?

Collection c = (5 == 5) ? new ArrayList() : new HashSet();

produces the following compiler error:

Incompatible conditional operand types ArrayList and HashSet

For reasons that I don't understand, the following fixes the problem

Collection c = (5 == 5) ? (Collection) new ArrayList() : new HashSet();

I'm using Java 1.4.

Thanks, Don

+5  A: 

This was a bug in 1.4 and has been fixed according bugreport 5080917.

Evaluation This is a bug.

xxxxx@xxxxx 2004-07-30

BalusC
+1 You are right. I misread the spec, and delete my answer now.
Daniel
That's a bug in 1.5 (tiger) fixed in 1.6 (mustang). It looks like a specific instance of the rule introduced in 1.5/3rd Ed JLS.
Tom Hawtin - tackline
@Daniel I think your answer was almost there.
Tom Hawtin - tackline
@Tom / @Daniel: I think *both* answers were after all correct. The new rules were introduced for 1.5 but there were bugs. Daniel however already got five upvotes for the 1st paragraph without pointing the 1.4/1.5 differences in any way before he copypasted some JLS cites (which I only saw after posting my answer).
BalusC
@BalusC There's always lots of bugs. The cited bug is irrelevant.
Tom Hawtin - tackline
+2  A: 

Daniel more or less gets this right, but has deleted his answer (with five up votes).

Relevant quote from 2nd Ed JLS (1.2-1.4)

  • If the second and third operands are of different reference types, then it must be possible to convert one of the types to the other type (call this latter type T) by assignment conversion (§5.2); the type of the conditional expression is T. It is a compile-time error if neither type is assignment compatible with the other type.

One of the types needs to be convertible to the other, which is not true of ArrayList and HashSet but is true of Collection and HashSet and of ArrayList and Collection.

In 3rd Ed JLS (1.5+)

  • Otherwise, the second and third operands are of types S1 and S2 respectively. Let T1 be the type that results from applying boxing conversion to S1, and let T2 be the type that results from applying boxing conversion to S2. The type of the conditional expression is the result of applying capture conversion (§5.1.10) to lub(T1, T2) (§15.12.2.7).

This does the obvious thing, which as it turns out is more difficult to specify and implement (I unintentionally got an early version of javac to crash on it when one of the expressions was void). IIRC, this was work done as part of generics.

Tom Hawtin - tackline