有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Eclipse bug?仅使用默认大小写打开空值

我在试验enum,发现以下代码在Eclipse上编译并运行良好(构建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) 个答案

  1. # 1 楼答案

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

    JLS 14.11 The ^{} Statement

    SwitchStatement:
        switch ( Expression ) SwitchBlock
    

    When the switch statement is executed, first the Expression is evaluated. If the Expression evaluates to null, a NullPointerException is thrown and the entire switch statement completes abruptly for that reason.

    显然,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(至少在某些版本)上编译并运行“良好”。当使用javac编译时,每个switch抛出一个NullPointerException,这正是规范要求的


    原因

    以下是在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

    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.

    另见

  2. # 2 楼答案

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

    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.

  3. # 3 楼答案

    当然。如果我们看一下java语言规范的chapter 14.11,它清楚地指出(在“讨论”下):

    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.