web-dev-qa-db-de.com

Was ist ein Initialisierungsblock?

Wir können Code in einen Konstruktor oder eine Methode oder einen Initialisierungsblock einfügen. Was ist der Initialisierungsblock? Ist es notwendig, dass jedes Java-Programm es haben muss? 

83
Sumithra

Zunächst gibt es zwei Arten von Initialisierungsblöcken :

  • Instanzinitialisierungsblöcke und
  • statische Initialisierungsblöcke.

Dieser Code soll die Verwendung von ihnen veranschaulichen und in welcher Reihenfolge sie ausgeführt werden:

public class Test {

    static int staticVariable;
    int nonStaticVariable;        

    // Static initialization block:
    // Runs once (when the class is initialized)
    static {
        System.out.println("Static initalization.");
        staticVariable = 5;
    }

    // Instance initialization block:
    // Runs each time you instantiate an object
    {
        System.out.println("Instance initialization.");
        nonStaticVariable = 7;
    }

    public Test() {
        System.out.println("Constructor.");
    }

    public static void main(String[] args) {
        new Test();
        new Test();
    }
}

Drucke:

Static initalization.
Instance initialization.
Constructor.
Instance initialization.
Constructor.

Instanzialisierungsblöcke sind hilfreich, wenn Sie Code ausführen möchten, unabhängig davon, welcher Konstruktor verwendet wird, oder wenn Sie eine Instanzinitialisierung für anonyme Klassen durchführen möchten.

157
aioobe

möchte @ aioobes Antwort hinzufügen

Reihenfolge der Ausführung:

  1. statische Initialisierungsblöcke von Superklassen

  2. statische Initialisierungsblöcke der Klasse

  3. instanzinitialisierungsblöcke von Superklassen

  4. Konstrukteure von Superklassen

  5. instanzinitialisierungsblöcke der Klasse

  6. konstruktor der Klasse.

Ein paar zusätzliche Punkte, die Sie beachten sollten (Punkt 1 ist eine Wiederholung der Antwort von @ aioobe):

  1. Der Code im statischen Initialisierungsblock wird zum Zeitpunkt des Klassenladens ausgeführt (und ja, das heißt nur einmal pro Klassenladevorgang), bevor Instanzen der Klasse erstellt werden und bevor statische Methoden aufgerufen werden.

  2. Der Instanzinitialisierungsblock wird tatsächlich vom Java-Compiler in jeden Konstruktor der Klasse kopiert. Also jedes Mal, wenn der Code im Instanzinitialisierungsblock genau vor dem Code im Konstruktor ausgeführt wird.

87
Biman Tripathy

Schöne Antwort von aioobe Hinzufügen weiterer Punkte

public class StaticTest extends parent {
    static {
        System.out.println("inside satic block");
    }

    StaticTest() {
        System.out.println("inside constructor of child");
    }

    {
        System.out.println("inside initialization block");
    }

    public static void main(String[] args) {
        new StaticTest();
        new StaticTest();
        System.out.println("inside main");
    }
}

class parent {
    static {
        System.out.println("inside parent Static block");
    }
    {
        System.out.println("inside parent initialisation block");
    }

    parent() {
        System.out.println("inside parent constructor");
    }
}

das gibt 

inside parent Static block
inside satic block
inside parent initialisation block
inside parent constructor
inside initialization block
inside constructor of child
inside parent initialisation block
inside parent constructor
inside initialization block
inside constructor of child
inside main

es ist wie das Offensichtliche, scheint aber etwas klarer.

6
Gaurav

Der Beispielcode, der hier als Antwort genehmigt wird, ist korrekt, aber ich stimme dem nicht zu. Es zeigt nicht, was passiert, und ich werde Ihnen ein gutes Beispiel zeigen, um zu verstehen, wie die JVM tatsächlich funktioniert:

package test;

    class A {
        A() {
            print();
        }

        void print() {
            System.out.println("A");
        }
    }

    class B extends A {
        static int staticVariable2 = 123456;
        static int staticVariable;

        static
        {
            System.out.println(staticVariable2);
            System.out.println("Static Initialization block");
            staticVariable = Math.round(3.5f);
        }

        int instanceVariable;

        {
            System.out.println("Initialization block");
            instanceVariable = Math.round(3.5f);
            staticVariable = Math.round(3.5f);
        }

        B() {
            System.out.println("Constructor");
        }

        public static void main(String[] args) {
            A a = new B();
            a.print();
            System.out.println("main");
        }

        void print() {
            System.out.println(instanceVariable);
        }

        static void somethingElse() {
            System.out.println("Static method");
        }
    }

Bevor Sie beginnen, den Quellcode zu kommentieren, werde ich Ihnen eine kurze Erläuterung der statischen Variablen einer Klasse geben:

Als Erstes werden sie als Klassenvariablen bezeichnet. Sie gehören zur Klasse und nicht zu einer bestimmten Instanz der Klasse. Alle Instanzen der Klasse teilen sich diese statische (Klassen-) Variable. Jede Variable hat einen Standardwert, je nach Grundelement oder Referenztyp. Eine andere Sache ist, wenn Sie die statische Variable in einigen der Member der Klasse (Initialisierungsblöcke, Konstruktoren, Methoden, Eigenschaften) neu zuweisen und dabei den Wert der statischen Variablen nicht für eine bestimmte Instanz ändern, sondern für alle Instanzen. Zum Abschluss des statischen Teils möchte ich sagen, dass die statischen Variablen einer Klasse nicht erstellt werden, wenn Sie die Klasse zum ersten Mal instanziieren. Sie werden erstellt, wenn Sie Ihre Klasse definieren. Sie sind in JVM vorhanden, ohne dass Instanzen erforderlich sind. Für den korrekten Zugriff statischer Member von externen Klassen (Klassen, in denen sie nicht definiert sind), verwenden Sie den Klassennamen, gefolgt von Punkt und dann den statischen Member, auf den Sie zugreifen möchten (template: <CLASS_NAME>.<STATIC_VARIABLE_NAME>).

Schauen wir uns den Code oben an:

Der Einstiegspunkt ist die Hauptmethode - es gibt nur drei Codezeilen. Ich möchte auf das derzeit genehmigte Beispiel verweisen. Demnach ist das erste, was nach dem Drucken von "Statischer Initialisierungsblock" gedruckt werden muss, "Initialisierungsblock", und hier ist meine Nichtübereinstimmung. Der nicht statische Initialisierungsblock wird nicht vor dem Konstruktor aufgerufen, er wird vor allen Initialisierungen der Konstruktoren aufgerufen der Klasse, in der der Initialisierungsblock definiert ist. Der Konstruktor der Klasse ist das erste, wenn Sie ein Objekt erstellen (Instanz der Klasse). Wenn Sie dann den Konstruktor eingeben, wird als erster Teil implizierter (Standard-) Superkonstruktor oder expliziter Superkonstruktor oder expliziter Aufruf eines anderen überladenen Objekts aufgerufen Konstruktor (wenn jedoch eine Kette überladener Konstruktoren vorhanden ist, ruft der letzte implizit oder explizit einen Superkonstruktor auf). 

Es gibt eine polymorphe Erstellung eines Objekts, aber bevor die Klasse B und ihre Hauptmethode eingegeben werden, initialisiert die JVM alle (statischen) Klassenvariablen, durchläuft dann die statischen Initialisierungsblöcke, falls vorhanden, und tritt dann in die Klasse B ein und beginnt mit der Ausführung der Hauptmethode. Es geht an den Konstruktor der Klasse B und ruft dann unmittelbar (implizit) den Konstruktor der Klasse A auf. Die Methode (überschriebene Methode), die im Rumpf des Konstruktors der Klasse A aufgerufen wird, ist diejenige, die in Klasse B und in diesem Fall definiert ist Die Variable mit dem Namen instanceVariable wird vor der Neuinitialisierung verwendet. Nach dem Schließen des Konstruktors der Klasse B wird der Thread an den Konstruktor der Klasse B zurückgegeben. Er wird jedoch zuerst in den nicht statischen Initialisierungsblock verschoben, bevor "Konstruktor" gedruckt wird. Für ein besseres Verständnis des Debuggens mit einer IDE ziehe ich Eclipse vor.

3
nenito

Der Initialisierungsblock enthält den Code, der immer ausgeführt wird, wenn eine Instanz erstellt wird. Es wird verwendet, um den gemeinsamen Teil verschiedener Konstruktoren einer Klasse zu deklarieren/zu initialisieren. 

Die Reihenfolge der Initialisierungskonstruktoren und des Initialisierungsblocks spielt keine Rolle, der Initialisierungsblock wird immer vor dem Konstruktor ausgeführt. 

Was ist, wenn wir einmal Code für alle Objekte einer Klasse ausführen möchten?

Wir verwenden Static Block in Java. 

1
roottraveller

Initialisierungsblöcke werden immer dann ausgeführt, wenn die Klasse initialisiert wird und bevor Konstruktoren aufgerufen werden. Sie werden normalerweise in Klammern über den Konstruktoren platziert. Es ist überhaupt nicht notwendig, sie in Ihre Klassen aufzunehmen.

Sie werden normalerweise zum Initialisieren von Referenzvariablen verwendet. Diese Seite gibt eine gute Erklärung

0
Gaurav Saxena

Initialismus Zeigt den Text im Element <abbr> in einer etwas kleineren Schriftgröße an

Die Frage ist nicht ganz klar, aber hier eine kurze Beschreibung, wie Sie Daten in einem Objekt initialisieren können. Nehmen wir an, Sie haben eine Klasse A, die eine Liste von Objekten enthält.

1) Geben Sie die Anfangswerte in die Felddeklaration ein:

class A {
    private List<Object> data = new ArrayList<Object>();
}

2) Weisen Sie im Konstruktor Anfangswerte zu:

class A {
    private List<Object> data;
    public A() {
        data = new ArrayList<Object>();
    }
}

Beide setzen voraus, dass Sie "Daten" nicht als Konstruktorargument übergeben möchten.

Die Dinge werden etwas schwierig, wenn Sie überladene Konstruktoren mit internen Daten wie oben mischen. Erwägen:

class B {
    private List<Object> data;
    private String name;
    private String userFriendlyName;

    public B() {
        data = new ArrayList<Object>();
        name = "Default name";
        userFriendlyName = "Default user friendly name";
    }

    public B(String name) {
        data = new ArrayList<Object>();
        this.name = name;
        userFriendlyName = name;
    }

    public B(String name, String userFriendlyName) {
        data = new ArrayList<Object>();
        this.name = name;
        this.userFriendlyName = userFriendlyName;
    }
}

Beachten Sie, dass es viel wiederholten Code gibt. Sie können dies beheben, indem Sie Konstruktoren dazu aufrufen, sich gegenseitig aufzurufen, oder Sie haben eine private Initialisierungsmethode, die jeder Konstruktor aufruft:

class B {
    private List<Object> data;
    private String name;
    private String userFriendlyName;

    public B() {
        this("Default name", "Default user friendly name");
    }

    public B(String name) {
        this(name, name);
    }

    public B(String name, String userFriendlyName) {
        data = new ArrayList<Object>();
        this.name = name;
        this.userFriendlyName = userFriendlyName;
    }
}

oder

class B {
    private List<Object> data;
    private String name;
    private String userFriendlyName;

    public B() {
        init("Default name", "Default user friendly name");
    }

    public B(String name) {
        init(name, name);
    }

    public B(String name, String userFriendlyName) {
        init(name, userFriendlyName);
    }

    private void init(String _name, String _userFriendlyName) {
        data = new ArrayList<Object>();
        this.name = name;
        this.userFriendlyName = userFriendlyName;
    }
}

Die beiden sind (mehr oder weniger) gleichwertig.

Ich hoffe, das gibt Ihnen einige Hinweise, wie Sie Daten in Ihren Objekten initialisieren. Ich werde nicht über statische Initialisierungsblöcke sprechen, da dies im Moment wahrscheinlich etwas fortgeschritten ist.

BEARBEITEN: Ich habe Ihre Frage als "Wie initialisiere ich meine Instanzvariablen" interpretiert, nicht "Wie funktionieren Initialisierungsblöcke?", Da Initialisierungsblöcke ein relativ fortgeschrittenes Konzept sind das einfachere Konzept. Ich könnte falsch liegen.

0
Cameron Skinner
public class StaticInitializationBlock {

    static int staticVariable;
    int instanceVariable;

    // Static Initialization Block
    static { 
        System.out.println("Static block");
        staticVariable = 5;

    }

    // Instance Initialization Block
    { 

        instanceVariable = 7;
        System.out.println("Instance Block");
        System.out.println(staticVariable);
        System.out.println(instanceVariable);

        staticVariable = 10;
    }


    public StaticInitializationBlock() { 

        System.out.println("Constructor");
    }

    public static void main(String[] args) {
        new StaticInitializationBlock();
        new StaticInitializationBlock();
    }

}

Ausgabe:

Static block
Instance Block
5
7
Constructor
Instance Block
10
7
Constructor