2012-05-16 17 views
68

¿Alguien podría explicar cómo Java ejecuta este código? Me refiero al orden de ejecución de cada declaración.Crear un objeto de forma estática

public class Foo 
{ 
    boolean flag = sFlag; 
    static Foo foo = new Foo(); 
    static boolean sFlag = true; 

    public static void main(String[] args) 
    { 
     System.out.println(foo.flag); 
    } 
} 

SALIDA:

false 
+4

Somos humanos, no ordenador. Deberíamos tratar de hacer el código más directo en lugar de usar este tipo de trucos o trampas o lo que sea ... –

+1

+1 porque no es una pregunta difícil pero buena, que estoy seguro ayudará a otros a entender el lenguaje y especialmente la estática modificador mejor. Respuesta muy útil dada por @JonSkeet sobre un tema algo importante, pero a menudo subestimado. – jorey

+1

No me gusta cuando la gente usa 'Foo'. Use términos reales:/ – contactmatt

Respuesta

104
  • Comienza la inicialización de la clase. Inicialmente, foo es nula y sFlag es falso
  • La primera inicializador de variable estática (foo) se ejecuta:
    • Se crea una nueva instancia de Foo
    • La instancia de inicialización variable para flag ejecuta - Actualmente sFlag es falso, por lo el valor de flag es falsa
  • el segundo inicializador variable estática (sFlag) ejecuta, estableciendo el valor a true
  • inicialización Clase completa
  • main carreras, la impresión de foo.flag, lo cual es falso

Tenga en cuenta que si sFlag fueron declarados final que sería tratado como un tiempo de compilación constante, momento en el cual todas las referencias a esto se limitarían básicamente a true, por lo que foo.flag sería cierto también.

+15

+1 Para una buena explicación y para 'final' :) –

+0

¿Importa el orden en que se definen las variables en la clase? es decir, si 'bandera' se definió después de' sflag'? – Naveen

+0

@Naveen En mi humilde opinión, no lo creo. las variables estáticas se inicializarán primero. –

12

foo se instancia durante la inicialización estático de la clase, y antes de sFlag se ha inicializado, y el valor predeterminado de un valor booleano es falso.

  1. La clase se carga
  2. Foo se inicializa a la instancia

    2.a La bandera miembro de instancia se inicializa con el valor de sFlag (false por defecto)

  3. sFlag se inicializa a cierto

Por favor refiérase a JLS §12.4 para más detalles.

5

Cuando se carga la clase, los campos sFlag y foo se inicializan pero foo se inicializa primero.
campos flag y sFlag son booleanos y no pueden ser nulos por lo que de forma predeterminada son falsos y sFlag sigue siendo falso cuando se inicializa foo. flag = sFlag después de esto flag es falso.Esto es

1

al principio, los campos estáticos deberían ejecutarse y al principio en línea!así que en la primera línea 4 y luego 5 se ejecutarán para que foo se inicialice primero y como sabemos que las variables booleanas se inicializan a falso de manera predeterminada así que al principio para que el foo se inicialice el campo de bandera es sflag que es falso y luego sfalsg se convierte en verdadero que no cambiará la bandera (no hay relación), luego, al final, se ejecutarán las principales e imprimirá fallas que son falsas. ¡Espero ser útil! Tener éxito

2

El orden general de operaciones de inicialización es (después de cargar la clase y antes del primer uso):

  1. estático (clase) bloques de código en el orden en que aparece en el código, código
  2. Objeto bloques para que aparezca en el código (bloques de inicialización y asignaciones).
  3. constructores

Ciertamente no me refiero constructores y funciones del cuerpo como un bloque de código anteriormente.

No sé qué tal final static campos. Parece que siguen las reglas de los campos static y no pueden referenciarse antes de la declaración a pesar de los comentarios anteriores de que se inicializaron en el paso de compilación. Si se hace referencia antes de que haya un error de compilación:

Example.java:8: illegal forward reference 
     System.err.println("1st static block j=" + j); 

Tal final static campos se puede inicializar y compilado en el archivo de clase, pero esto no es una regla general y que todavía no se puede hacer referencia antes de la declaración.

Ejemplo de código para comprobar orden de inicialización:

class Example {  

    final static int j = 5; 

    { 
     System.err.println("1st initializer j=" + j); 
    } 

    static { 
     System.err.println("1st static block j=" + j); 
    } 

    static { 
     System.err.println("2nd static block j=" + j); 
    } 

    final static java.math.BigInteger i = new java.math.BigInteger("1") {  
     { 
      System.err.println("final static anonymous class initializer"); 
     } 
    }; 

    Example() { 
     System.err.println("Constructor"); 
    } 

    static { 
     System.err.println("3nd static block j=" + j); 
    } 

    { 
     System.err.println("2nd initializer"); 
    } 

    public static void main(String[] args) { 
     System.err.println("The main beginning."); 
     Example ex = new Example(); 
     System.err.println("The main end."); 
    } 
} 

Las impresiones de código snipset anteriores:

1st static block j=5 
2nd static block j=5 
final static anonymous class initializer 
3nd static block j=5 
The main beginning. 
1st initializer j=5 
2nd initializer 
Constructor 
The main end. 
+0

especificación de JVM [Procedimiento detallado de inicialización] (http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4 .2) –

Cuestiones relacionadas