Llamar a un método Java sin nombre

101

Estoy mirando el código a continuación y encontré algo un poco extraño:

public class Sequence {
    Sequence() {
        System.out.print("c ");
    }

    {
        System.out.print("y ");
    }

    public static void main(String[] args) {
        new Sequence().go();
    }

    void go() {
        System.out.print("g ");
    }

    static {
        System.out.print("x ");
    }
}

Hubiera esperado que esto diera un error de compilación ya que System.outcon "y" no pertenece a una declaración de método solo a { }. ¿Por qué es esto válido? No veo cómo se llamaría o debería llamarse este código.

Al ejecutar esto, x y c gtambién produce , ¿por qué static { }se llama antes del constructor de secuencia?

david99world
fuente

Respuestas:

149

Esta:

static {
        System.out.print("x ");
    }

es un bloque de inicialización estático y se llama cuando se carga la clase. Puede tener tantos de ellos en su clase como desee, y se ejecutarán en el orden de aparición (de arriba a abajo).

Esta:

    {
        System.out.print("y ");
    }

es un bloque de inicialización y el código se copia al principio de cada constructor de la clase. Entonces, si tiene muchos constructores de su clase, y todos necesitan hacer algo común al principio, solo necesita escribir el código una vez y ponerlo en un bloque de inicialización como este.

Por lo tanto, su salida tiene mucho sentido.

Como Stanley comentó a continuación, consulte la sección del tutorial de Oracle que describe los bloques de inicialización para obtener más información.

jlordo
fuente
12
Gran respuesta. Obtenga más información sobre el bloqueo de inicialización en http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
Stanley
6
the code is copied into the beginning of each constructor of the class- Esto es incorrecto. Digamos que el constructor comienza con super("x ");, el superconstructor se ejecutará antes de cualquier bloque de inicialización.
RokL
3
sí, las llamadas implícitas y explícitas al superconstructor se ejecutarán primero, luego el bloque de inicialización y luego el resto del código del constructor.
jlordo
25

No es un método sino un bloque de inicialización .

 {
    System.out.print("y ");
 }

Se ejecutará antes de la llamada al constructor. Mientras

static {
        System.out.print("x ");
       }

es un bloque de inicialización estático que se ejecuta cuando el cargador de clases carga la clase.

Entonces, cuando ejecuta su código
1. El cargador de clases carga la clase para que se ejecute el bloque de inicialización estático
Salida: se imprime x
2. Se crea el objeto para que se ejecute el bloque de inicialización y luego el constructor se llama
Salida: y se imprime seguido de c
3. Se invoca el método principal que a su vez invoca el método go
Salida: se imprime g

Resultado final: xycg
Esto podría ayudar http://blog.sanaulla.info/2008/06/30/initialization-blocks-in-java/

xyz
fuente
@Cthulhu: Gracias. Era válido hasta la semana pasada que lo he actualizado con un nuevo enlace.
xyz
16

Ese es un bloque de inicialización de instancia seguido de un bloque de inicialización estático .

{
    System.out.print("y ");
}

se llama cuando crea una instancia de la clase.

static {
    System.out.print("x ");
}

se llama cuando el cargador de clases carga la clase. Así que cuando lo hagas

new Sequence().go();

la clase se carga, entonces se ejecuta static {}, luego ejecuta el bloque de inicialización de la instancia {}, luego se llama al cuerpo del constructor y luego al método en la instancia recién creada. Ergo la salida x y c g.

Luchian Grigore
fuente
15
static {
        System.out.print("x ");
    }

Es un bloque estático y se llama durante la carga de clases.

{
    System.out.print("y ");
}

Es un bloque de inicialización

Puede tener varios bloques de inicialización en una clase, en cuyo caso se ejecutan en la secuencia en la que aparecen en la clase.

Tenga en cuenta que cualquier bloque de inicialización presente en la clase se ejecuta antes que el constructor.

Narendra Pathai
fuente
10
static {
      System.out.print("x ");
}

es un bloque de inicialización compartido por la clase (como lo indica static), que se ejecuta primero.

{
        System.out.print("y ");

}

es un bloque de inicialización compartido por todos los objetos (constructores) de la clase, que viene a continuación.

Sequence() {
        System.out.print("c ");
}

es un constructor particular para la clase, que se ejecuta en tercer lugar. El bloque de inicialización de la instancia se invoca primero cada vez que se ejecuta el constructor. Es por eso que "y" viene justo antes de "c".

void go() {
        System.out.print("g ");
}

es solo un método de instancia asociado con objetos construidos usando el constructor anterior, que es el último.

Terry Li
fuente
9
{
    System.out.print("y ");
}

Este tipo de bloques se denominan initializer block. Se ejecuta cada vez que crea una instancia de class. En tiempo de compilación, este código se mueve a cada constructor de su clase.

Donde, como en el caso del static initializerbloque: -

static {
    System.out.println("x ");
}

se ejecuta una vez cuando se carga la clase. Generalmente usamos el staticbloque inicializador cuando la inicialización de un staticcampo requiere varios pasos.

Rohit Jain
fuente
6

Se utiliza como bloque de inicialización y se ejecuta después de cualquier declaración estática . Podría usarse para garantizar que nadie más pueda crear una instancia de la clase (de la misma manera que usaría un constructor privado) como con el patrón de diseño Singleton .

maloney
fuente
3
static {
    System.out.print("x ");
}

Static blockssolo se ejecutan una vez cuando el JRE carga e inicializa la clase .

Y non-staticse llamará al bloque cada vez que esté creando una nueva instancia y se llamará justo antes del Constructor.

Como aquí ha creado, solo Sequencese ha llamado 1 instancia de así construido después de los non-staticbloques y luego el método que realmente es su objetivo.

Subhrajyoti Majumder
fuente