I was experimenting with enum
, and I found that the following compiles and runs fine on Eclipse (Build id: 20090920-1017, not sure exact compiler version):
Definitly. If we look at the chapter 14.11 of the java language specification, it clearly states (under 'discussion'):
The prohibition against using null as a switch label prevents one from writing code that can never be executed. If the switch expression is of a reference type, such as a boxed primitive type or an enum, a run-time error will occur if the expression evaluates to null at run-time.
This is a bug. Here's the specified behavior for a switch
statement according to the Java Language Specification, 3rd Edition:
SwitchStatement: switch ( Expression ) SwitchBlock
When the
switch
statement is executed, first theExpression
is evaluated. If theExpression
evaluates tonull
, aNullPointerException
is thrown and the entireswitch
statement completes abruptly for that reason.
Apparently the bug in Eclipse has nothing to do with default
case or enum
at all.
public class SwitchingOnAnull {
public static void main(String[] args) {
java.math.RoundingMode x = null;
switch(x) {};
switch((Integer) null) {};
switch((Character) null) {
default: System.out.println("I've got sunshine!");
}
}
}
The above code compiles and runs "fine" on (at least some version of) Eclipse. Each individual switch
throws a NullPointerException
when compiled with javac
, which is exactly as the specification mandates.
Here's javap -c SwitchingOnAnull
when compiled under Eclipse:
Compiled from "SwitchingOnAnull.java"
public class SwitchingOnAnull extends java.lang.Object{
public SwitchingOnAnull();
Code:
0: aload_0
1: invokespecial #8; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: aconst_null
1: astore_1
2: getstatic #16; //Field java/lang/System.out:Ljava/io/PrintStream;
5: ldc #22; //String I've got sunshine!
7: invokevirtual #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
10: return
}
It seems that the Eclipse compiler gets rid of the entire switch
constructs entirely. Unfortunately this optimization breaks the language specification.
The bug has been filed and assigned for fix.
Olivier Thomann 2010-05-28 08:37:21 EDT
We are too aggressive on the optimization.
For:
switch((Integer) null) {};
we optimize out the whole
switch
statement when we should at least evaluate the expression.I'll take a look.
Candidate for 3.6.1.
Yep. According to the JLS it's a bug:
If the switch expression is of a reference type, such as a boxed primitive type or an enum, a run-time error will occur if the expression evaluates to null at run-time.