Aufruf einer Java-Methode ohne Namen

100

Ich schaue auf den Code unten und finde etwas Seltsames:

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

Ich hätte erwartet, dass dies zu einem Kompilierungsfehler führt, da das System.outmit "y" nicht zu einer Methodendeklaration gehört, sondern nur zu a { }. Warum ist das gültig? Ich sehe nicht, wie dieser Code aufgerufen werden würde oder sollte.

Wenn dies ausgeführt wird, wird x y c gauch erzeugt , warum wird das static { }vor dem Sequenzkonstruktor aufgerufen?

david99world
quelle

Antworten:

148

Dies:

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

ist ein statischer Initialisierungsblock und wird beim Laden der Klasse aufgerufen. Sie können so viele von ihnen in Ihrer Klasse haben, wie Sie möchten, und sie werden in der Reihenfolge ihres Auftretens (von oben nach unten) ausgeführt.

Dies:

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

ist ein Initialisierungsblock , und der Code wird in den Anfang jedes Konstruktors der Klasse kopiert. Wenn Sie also viele Konstruktoren Ihrer Klasse haben und alle zu Beginn etwas Gemeinsames tun müssen, müssen Sie den Code nur einmal schreiben und in einen Initialisierungsblock wie diesen einfügen .

Daher ist Ihre Ausgabe absolut sinnvoll.

Als Stanley unten kommentiert, siehe den Abschnitt im Tutorial Oracle initializaiton Blöcken beschreibt für weitere Informationen.

jlordo
quelle
12
Gute Antwort. Weitere Informationen zum Initialisierungsblock finden Sie unter 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- Das ist falsch. Angenommen, der Konstruktor beginnt mit super("x ");, der Superkonstruktor wird vor allen Initialisierungsblöcken ausgeführt.
RokL
3
Ja, implizite und explizite Aufrufe des Superkonstruktors werden zuerst ausgeführt, der Initialisierungsblock als nächstes und dann der Rest des Konstruktorcodes.
Lordo
25

Es ist keine Methode, sondern ein Initialisierungsblock .

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

Es wird vor dem Konstruktoraufruf ausgeführt. Während

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

ist ein statischer Initialisierungsblock, der ausgeführt wird, wenn die Klasse vom Klassenladeprogramm geladen wird.

Wenn Sie also Ihren Code
1 ausführen, wird die Klasse vom Klassenladeprogramm geladen, sodass der statische Initialisierungsblock ausgeführt wird.
Ausgabe: x wird gedruckt.
2. Das Objekt wird so erstellt, dass der Initialisierungsblock ausgeführt wird, und dann wird der Konstruktor
Ausgabe ausgegeben : y wird gedruckt, gefolgt von c
3. Die Hauptmethode wird aufgerufen, die wiederum die go-Methode aufruft.
Ausgabe: g wird gedruckt

Endgültige Ausgabe: xycg
Dies könnte hilfreich sein http://blog.sanaulla.info/2008/06/30/initialization-blocks-in-java/

xyz
quelle
@Cthulhu: Danke. Es war bis letzte Woche gültig. Ich habe es mit einem neuen Link aktualisiert.
XYZ
16

Dies ist ein Instanzinitialisierungsblock, gefolgt von einem statischen Initialisierungsblock .

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

wird aufgerufen, wenn Sie eine Instanz der Klasse erstellen.

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

wird aufgerufen, wenn die Klasse vom Klassenladeprogramm geladen wird. Also wenn du es tust

new Sequence().go();

Die Klasse wird geladen, also ausgeführt static {}, dann wird der Instanzinitialisierungsblock ausgeführt {}, anschließend wird der Hauptteil des Konstruktors aufgerufen und anschließend die Methode für die neu erstellte Instanz. Ergo die Ausgabe x y c g.

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

Ist ein statischer Block und wird beim Laden der Klasse aufgerufen

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

Ist ein Initialisierungsblock

Sie können mehrere Initialisierungsblöcke in einer Klasse haben. In diesem Fall werden sie in der Reihenfolge ausgeführt, in der sie in der Klasse angezeigt werden.

Beachten Sie, dass alle in der Klasse vorhandenen Initialisierungsblöcke vor dem Konstruktor ausgeführt werden.

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

ist ein von der Klasse gemeinsam genutzter Initialisierungsblock (wie durch angegeben static), der zuerst ausgeführt wird.

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

}

ist ein Initialisierungsblock, der von allen Objekten (Konstruktoren) der Klasse gemeinsam genutzt wird.

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

ist ein bestimmter Konstruktor für die Klasse, die als dritter ausgeführt wird. Der Instanzinitialisierungsblock wird bei jeder Ausführung des Konstruktors zuerst aufgerufen. Deshalb kommt "y" kurz vor "c".

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

ist nur eine Instanzmethode, die Objekten zugeordnet ist, die mit dem obigen Konstruktor erstellt wurden.

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

Diese Arten von Blöcken werden aufgerufen initializer block. Es wird jedes Mal ausgeführt, wenn Sie eine Instanz von a erstellen class. Zur Kompilierungszeit wird dieser Code in jeden Konstruktor Ihrer Klasse verschoben.

Wo wie im Fall von static initializerBlock: -

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

Es wird einmal ausgeführt, wenn die Klasse geladen wird. Wir verwenden im Allgemeinen den staticInitialisierungsblock, wenn die Initialisierung eines staticFeldes mehrere Schritte erfordert.

Rohit Jain
quelle
6

Es wird als Initialisierungsblock verwendet und nach jeder statischen Deklaration ausgeführt . Es kann verwendet werden, um sicherzustellen, dass niemand eine Instanz der Klasse erstellen kann (auf die gleiche Weise, wie Sie einen privaten Konstruktor verwenden würden), wie dies beim Singleton- Entwurfsmuster der Fall ist.

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

Static blockswerden nur einmal ausgeführt, wenn die Klasse von der JRE geladen und initialisiert wird.

Der non-staticBlock wird jedes Mal aufgerufen, wenn Sie eine neue Instanz erstellen, und er wird direkt vor dem Konstruktor aufgerufen.

Da Sie hier nur eine Instanz von Sequenceso konstruierten erstellt haben, wurde nach non-staticBlöcken aufgerufen und dann die Methode, die eigentlich Ihr Ziel ist.

Subhrajyoti Majumder
quelle