Eclipse ошибка? Переключение на ноль только с регистром по умолчанию
Я экспериментировал с enum
и я обнаружил, что следующие компоненты компилируются и нормально работают на Eclipse (идентификатор сборки: 20090920-1017, точная версия компилятора точно не определена):
public class SwitchingOnAnull {
enum X { ,; }
public static void main(String[] args) {
X x = null;
switch(x) {
default: System.out.println("Hello world!");
}
}
}
При компиляции и запуске с Eclipse, это печатает "Hello world!"
и выходит нормально.
С javac
компилятор, это бросает NullPointerException
как и ожидалось.
Так есть ли ошибка в компиляторе Eclipse Java?
3 ответа
Это ошибка. Вот указанное поведение для switch
заявление в соответствии со спецификацией языка Java, 3-е издание:
JLS 14.11 switch
утверждение
SwitchStatement: switch ( Expression ) SwitchBlock
Когда
switch
оператор выполняется, сначалаExpression
оценивается. ЕслиExpression
оцениваетnull
,NullPointerException
брошен и весьswitch
заявление завершается внезапно по этой причине.
Видимо ошибка в Eclipse не имеет ничего общего с default
случай или enum
совсем.
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!");
}
}
}
Приведенный выше код компилируется и работает "отлично" на (по крайней мере, в некоторых версиях) Eclipse. Каждый человек switch
бросает NullPointerException
при компиляции с javac
, что именно так, как указано в спецификации.
Причина
Вот javap -c SwitchingOnAnull
когда скомпилировано под 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
}
Кажется, что компилятор Eclipse избавляется от всего switch
конструирует целиком К сожалению, эта оптимизация нарушает спецификацию языка.
Официальные слова
Ошибка была подана и назначена для исправления.
Оливье Томанн 2010-05-28 08:37:21 ПО ВОСТОЧНОМУ ВРЕМЕНИ
Мы слишком агрессивны в оптимизации.
За:
switch((Integer) null) {};
мы оптимизируем весь
switch
заявление, когда мы должны хотя бы оценить выражение.Я взгляну.
Кандидат на 3.6.1.
Смотрите также
- Ошибка 314830 - Включение
null
выражение не всегда бросаетNullPointerException
Определенно. Если мы посмотрим на главу 14.11 спецификации языка Java, она четко говорит (в разделе "обсуждение"):
Запрет на использование null в качестве метки переключателя не позволяет писать код, который никогда не будет выполнен. Если выражение switch относится к ссылочному типу, такому как тип примитива в штучной упаковке или enum, во время выполнения произойдет ошибка, если выражение оценивается как ноль во время выполнения.
Ага. Согласно JLS это ошибка:
Если выражение switch относится к ссылочному типу, такому как тип примитива в штучной упаковке или enum, во время выполнения произойдет ошибка, если выражение оценивается как ноль во время выполнения.