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

pol*_*nts 31 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!");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在使用Eclipse编译和运行时,这将"Hello world!"正常打印和退出.

使用javac编译器,这NullPointerException将按预期抛出.

那么Eclipse Java编译器中是否存在错误?

pol*_*nts 27

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

JLS 14.11 switch声明

SwitchStatement:
    switch ( Expression ) SwitchBlock
Run Code Online (Sandbox Code Playgroud)

switch执行语句时,首先Expression评估该语句.如果Expression求值为null,NullPointerException则抛出a并且整个switch语句因此而突然完成.

显然,Eclipse中的错误与defaultcase 无关或完全无关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!");
        }       
    }
}
Run Code Online (Sandbox Code Playgroud)

上面的代码编译并在Eclipse(至少某些版本)上运行"正常".每个人在编译时都会switch抛出一个,这与规范要求完全一致.NullPointerExceptionjavac


原因

这是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

}
Run Code Online (Sandbox Code Playgroud)

似乎Eclipse编译器switch完全摆脱了整个构造.不幸的是,这种优化打破了语言规范


官方的话

该错误已被提交并分配用于修复.

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

我们在优化方面过于激进.

对于:

  switch((Integer) null) {};
Run Code Online (Sandbox Code Playgroud)

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

我会看一看.

候选人为3.6.1.

也可以看看

  • 那很好笑.在实施优化时,一些EDT开发人员有点*太聪明了. (5认同)
  • @darren没有.Eclipse有自己的编译器,完全独立于`javac`.执行stackoverflow搜索"eclipse javac",你会看到有很多情况(特别是与泛型相关),它们的行为方式不同. (3认同)
  • @aioobe - 你是对的,他们太聪明了.他们以语言定义没有意义的方式实现它.抛出异常而不是违约是绝对迟钝的.现在我必须为一个NullPointerException包装一个try/catch,其中catch将执行与默认操作完全相同的操作.编辑:实际上,我会插入一个空检查,它比等待捕获异常更快,特别是因为它是预期的. (2认同)