Eclipse bug?仅使用默认情况打开null

时间:2010-05-28 05:42:46

标签: java eclipse null enums switch-statement

我正在尝试使用enum,我发现以下编译并在Eclipse上运行正常(Build id: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 个答案:

答案 0 :(得分:27)

这是一个错误。以下是根据 Java语言规范,第3版switch语句的指定行为:

JLS 14.11 The switch Statement

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,这与规范要求完全相同。


原因

在Eclipse下编译时,这里是javap -c SwitchingOnAnull

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构造。不幸的是,这种优化打破了语言规范。


官方用语

该错误已归档并已分配用于修复。

  

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

     

我们对优化过于激进。

     

有关:

  switch((Integer) null) {};
     

当我们至少应该评估时,我们会优化整个switch语句   表达

     

我会看看。

     

3.6.1的候选人。

另见

答案 1 :(得分:4)

Definitly。如果我们查看java语言规范的chapter 14.11,它会明确指出(在'讨论'下):

  

禁止使用null作为   一个开关标签阻止了一个   编写永远不会的代码   执行。如果切换表达式是   参考类型,例如盒装   原始类型或枚举,运行时   如果表达式将发生错误   在运行时计算为null。

答案 2 :(得分:1)

是的。根据JLS,这是一个错误:

  

如果switch表达式是引用类型,例如盒装基元类型或枚举,如果表达式在运行时求值为null,则会发生运行时错误。