java - visual - Error Eclipse? Activar un nulo con solo caso por defecto




windowbuilder eclipse oxygen (2)

Estaba experimentando con enum , y encontré que lo siguiente compila y funciona bien en Eclipse (Id. De compilación: 20090920-1017, no estoy seguro de la versión exacta del compilador):

public class SwitchingOnAnull {
    enum X { ,; }
    public static void main(String[] args) {
        X x = null;
        switch(x) {
            default: System.out.println("Hello world!");
        }
    }
}

Cuando se compila y ejecuta con Eclipse, esto imprime "Hello world!" y sale normalmente.

Con el compilador javac , esto lanza una NullPointerException como se esperaba.

Entonces, ¿hay algún error en el compilador de Eclipse Java?


Definitivamente. Si nos fijamos en el capítulo 14.11 de la especificación del lenguaje Java, indica claramente (en "discusión"):

La prohibición de usar nulo como una etiqueta de conmutador impide que uno escriba código que nunca se puede ejecutar. Si la expresión de cambio es de un tipo de referencia, como un tipo primitivo encuadrado o una enumeración, se producirá un error en tiempo de ejecución si la expresión se evalúa como nula en tiempo de ejecución.


Este es un error. Aquí está el comportamiento especificado para una declaración de switch acuerdo con la especificación del lenguaje Java, 3ª edición :

JLS 14.11 La declaración del switch

SwitchStatement:
    switch ( Expression ) SwitchBlock

Cuando se ejecuta la instrucción switch , primero se evalúa la Expression . Si la Expression evalúa como null , se lanza una NullPointerException y toda la instrucción del switch completa abruptamente por ese motivo.

Al parecer, el error en Eclipse no tiene nada que ver con default caso default o enum en absoluto.

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!");
        }       
    }
}

El código anterior compila y ejecuta "fino" en (al menos alguna versión de) Eclipse. Cada switch individual lanza una NullPointerException cuando se compila con javac , que es exactamente como los mandatos de la especificación.

La causa

Aquí está javap -c SwitchingOnAnull cuando se compila bajo 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

}

Parece que el compilador de Eclipse se deshace de las construcciones completas del switch completo. Desafortunadamente, esta optimización rompe la especificación del lenguaje.

Las palabras oficiales

El error ha sido archivado y asignado para su reparación.

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

Somos demasiado agresivos en la optimización.

Por:

  switch((Integer) null) {};

optimizamos toda la instrucción switch cuando deberíamos al menos evaluar la expresión.

Le daré un vistazo.

Candidato para 3.6.1.

Ver también





switch-statement