Community
Participate
Working Groups
Build ID: M20070921-1145 Steps To Reproduce: 1. Write code with incompatible types between switch and case statement: public class SwitchTest { public static void main(String[] args) { Integer d = 10 ; final short k = 100; switch (d) { case k: } } } 2. save, run as java application, note it's successful 3. attempt to compile with javac (1.6.0_05) 4. note error when compiling: SwitchTest.java:7: incompatible types found : short required: java.lang.Integer case k: ^ More information:
It seems that autoboxing rules have evolved in latest JDK versions. None of the integral subtypes (short, byte, char) seem to be auto-boxable into Integer any longer. public class X { public void foo() { Integer i1 = 10 ; final short s = 100; i1 = s; switch (i1) { case s: } } public void bar() { Integer i2 = 10 ; final byte b = 100; i2 = b; switch (i2) { case b: } } public void baz() { Integer i3 = 10 ; final char c = 100; i3 = c; switch (i3) { case c: } } }
Tested against build 1.7.0-ea-b25, build 1.6.0_10-beta-b20 and build 1.5.0_16-ea-b01. X.java:5: incompatible types found : short required: java.lang.Integer i1 = s; ^ X.java:8: incompatible types found : short required: java.lang.Integer case s: ^ X.java:14: incompatible types found : byte required: java.lang.Integer i2 = b; ^ X.java:17: incompatible types found : byte required: java.lang.Integer case b: ^ X.java:23: incompatible types found : char required: java.lang.Integer i3 = c; ^ X.java:26: incompatible types found : char required: java.lang.Integer case c: ^ 6 errors
According to http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6578574, javac would be considered as wrong in this instance. Yet, as far as JLS 3 is concerned, there seems to be no valid path to assign a short to an Integer (short would be boxed to Short, which does not extend Integer; widening short to int then boxing it to Integer is not permitted - see §5.2 on assignment conversions). Moreover, the switch/case behavior is specified as aligned with assignment (§14.11). Note also that javac hasn't changed recently wrt this peculiar behavior (tested a few versions). Bottom-line: - the current behavior of javac matches the spec, which mandates an error; - there is an accepted javac bug that asks for a the error be suppressed.
Feels like we were wrong since day 1 by assuming a widening conversion before boxing for assignment conversion, JLS 5.2 doesn't support it.
The Eclipse compiler correctly prevents boxing from short to Integer already, e.g. short s = 0; Integer i = s; // error already The issue only arises in presence of constant values being boxed as part of the representation question (a short can be represented as an int).
Interestingly javac does accept the following: Short si = (byte) 0; where it requires widening before boxing to Short (against the JLS 5.2, which only allows widening conversion to be performed for constants).
[ignore previous comment] Interestingly javac does accept the following: Short si = (byte) 0; where it requires widening before boxing to Short (against the JLS 5.2, which only allows narrowing conversion to be performed for constants).
Added AutoboxingTest#test165-test166 with present behavior.
Spec master confirmed this should be allowed, and is currently a hole in the spec itself. "This does look like a spec hole.. [...] JLS 5.2 should allow: "a widening primitive conversion (5.1.2), ***optionally followed by a boxing conversion***". The switch code in 6578574 would then compile." Also see: http://bugs.sun.com/view_bug.do?bug_id=6558543 Closing as a bug in javac&spec.
Verified for 3.5M2