Ошибка 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 компилятор, это бросает a NullPointerException как ожидалось.

Так в компиляторе Java Eclipse существует ли ошибка?

31
задан polygenelubricants 28 May 2010 в 05:42
поделиться

3 ответа

Это ошибка. Вот указанное поведение оператора switch в соответствии со спецификацией языка Java , 3-е издание :

JLS 14.11 switch Оператор

 SwitchStatement:
переключатель (Выражение) SwitchBlock

Когда выполняется оператор switch , сначала оценивается Выражение . Если выражение оценивается как null , возникает исключение NullPointerException , и по этой причине весь оператор switch завершается внезапно.

По-видимому, ошибка в Eclipse не имеет ничего общего с регистром по умолчанию или перечислением вообще.

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. Каждый отдельный переключатель генерирует исключение 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 полностью избавляется от всех конструкций переключателя . К сожалению, эта оптимизация нарушает спецификацию языка.


Официальные слова

Ошибка подана и назначена для исправления.

Olivier Thomann 28-05-2010, 08:37:21 EDT

Мы слишком агрессивны в оптимизации.

Для:

  переключатель ((Целое число) ноль) {};

мы оптимизируем весь оператор switch , когда мы должны хотя бы оценить выражение.

Я посмотрю.

Кандидат в 3.6.1.

См. Также

27
ответ дан 27 November 2019 в 22:43
поделиться

Определенно. Если мы посмотрим на главу 14.11 спецификации языка java, то в ней четко указано (в «обсуждении»):

Запрет на использование null в качестве метка переключателя предотвращает писать код, который никогда не может быть выполнен. Если выражение переключателя ссылочного типа, например в штучной упаковке примитивный тип или перечисление, время выполнения ошибка произойдет, если выражение оценивается как null во время выполнения.

4
ответ дан 27 November 2019 в 22:43
поделиться

Ага. Согласно JLS это ошибка:

Если выражение switch имеет ссылочный тип, такой как коробочный примитивный тип или перечисление, произойдет ошибка времени выполнения, если выражение во время выполнения оценивается в null.

1
ответ дан 27 November 2019 в 22:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: