Java Tutorial #15

Java Initializer

2018-11-10 | credit: RS-Studios

Thema in Kurzform

Initializer sind spezielle Methoden ohne Methodenkopf.

static-Initializer werden mit dem Schlüsselwort static eingeleitet und werden bei der ersten Benutzung der Klasse automatisch aufgerufen.

Instanz-Initializer

Dass die Anweisungen von Konstruktoren und Methoden immer zwischen zwei geschweiften Klammern { // Code } stehen, ist uns längst schon klar. Auch der Code von Initializern steht innerhalb eines Paars geschweifter Klammern. Aber: Es gibt bei Initializern keinen "Kopf", der vor dem Code-Block steht. Auch ein spezielles einleitendes Schlüsselwort (wie if, switch, while usw.) gibt es nicht. 

Initializer sehen also wie anonyme Methoden aus:

public class Cat {
    { System.out.println("Ich bin der Initializer!"); }
}

Diese Art von Initializer werden bei der Objekterzeugung automatisch ausgeführt, weshalb sie "Instanz"-Initializer heißen. Das Besondere: Die Ausführung geschieht noch vor dem Konstruktor-Aufruf:

public class Cat {

    public Cat(){
        System.out.println("Ich bin der Konstruktor");
    }

    { System.out.println("Ich bin der Initializer!"); }

    public static void main(String[] main){
        Cat c = new Cat(); // Cat-Objekt erzeugen
    }
}

Da zuerst der Instanz-Initializer und danach der Konstruktor ausgeführt wird, lautet der Output auf der Konsole so:

Ich bin der Initializer!
Ich bin der Konstruktor

Es gibt einige Regeln für Instanz-Initializer bei der Objekterzeugung:

  • Initializer werden vor den Konstruktoren der Klasse ausgeführt
  • Es kann mehrere Initializer geben.
  • Initializer stehen üblicherweise oben im Klassencode, was aber keine Pflicht ist.
  • Bei der Objekterzeugung werden die Initializer in der Reihenfolge ausgeführt, in der sie geschrieben stehen.
  • Nicht vergessen: Instanzvariablen haben den gleichen Stellenwert wie Instanz-Initializer. Sie werden gemeinsam mit diesen (entsprechend ihrer Reihenfolge) initialisiert.

Alles verstanden? Dann sagen Sie mal, was der folgende Code ausgibt:

public class Cat {

    private String name = "Simba";

     public Cat(){
        name = "Bailey";
        System.out.println("Cats are liquid");
    }

    public static void main(String[] main){
        Cat c = new Cat();
        System.out.println(c.name);
    }

    { System.out.println("Cats are jerks"); }
}

Dieser Code printed: 

Cats are jerks
Cats are liquid
Bailey

Klar warum? 😀 Zuerst wird innerhalb der Main-Methode ein neues Cat-Objekt erzeugt. Das hat zur Folge, dass die Instanzvariable name mit dem String "Simba" initialisiert und sofort darauf der Instanz-Initializer in Zeile 15 aufgerufen wird, der Cats are jerks printed. Erst danach wird in Zeile 5 der Konstruktor der Klasse aufgerufen. Dieser ändert den Wert von name in Bailey und printed den Text Cats are liquid auf der Konsole. Damit ist das neue Cat-Objekt fertig erstellt. Zu guter Letzt wird noch der letzte Wert von name auf der Konsole ausgegeben.

static-Initializer

Wenn Sie anfangs noch überrascht waren, dass es mit Instanz-Initializern Code gibt, der noch vor dem Konstruktor ausgeführt wird, dann passen Sie gut auf, denn es geht noch mehr: Mit dem static-Initializer können wir einen Code-Block sogar noch eine Stufe früher ausführen.

Static-Initializer werden gebildet wie Instanz-Initializer aber mit dem öffnenden Schlüsselwort static. Sehen wir uns hierzu einmal die Klasse StaticCat an:

public class StaticCat {

    public StaticCat(){
        System.out.println("Ich bin der Konstruktor");
    }

    { System.out.println("Ich bin ein Instanz-Initializer."); }

    static{
      System.out.println("Ich bin der static-Initializer!"); }

    public static void main(String[] main){
        StaticCat sc = new StaticCat();
    }
}

Ausgabe: 

Ich bin der static-Initializer!
Ich bin ein Instanz-Initializer.
Ich bin der Konstruktor

Die Sache läuft so ab: Noch bevor es ein StaticCat-Objekt gibt, quasi bei der ersten Benutzung der Klasse(!), wird der static-Initializer ausgeführt. 

Wir hätten uns die Objekterzeugung in Zeile 13 also auch sparen können: Der Static-Initializer wird trotzdem ausgeführt. Wir haben den Instanz-Initializer und Konstruktor nur eingebaut, um die Reihenfolge der Code-Ausführung zu zeigen.

Da der static-Initialzer (von dem es auch mehrere in einer Klasse geben kann) somit von der Klasse abhängt, kann er auch als "Klassen-Initializer" bezeichnet werden. Static-Initializer werden auch nur ein einziges Mal ausgeführt.

Static-Initializer wurden speziell für die Initialisierung von statischen Klassenvariablen und Konstanten erfunden:

public class StaticCat {

   public static final String NAME;

    static{
        NAME = "Hero";
    }
}

Fällt Ihnen an diesem Code irgendetwas auf? Richtig: "Eigentlich" müssen Konstanten wie NAME sofort initialisiert werden, ansonsten gibt es einen Compiler-Fehler. Tatsächlich geschieht dies hier auch (die Regel gilt also weiterhin), wenngleich nicht in derselben Anweisung. Der Grund: Der static-Initializer ist der erste Code, der überhaupt ausgeführt wird und damit geht die Sache hier in Ordnung! 😎

Wie bei statischen Methoden gilt auch bei statischen Initializern, dass sie niemals auf Instanz-Elemente (Instanzvariablen, Instanz-Methoden) zugreifen können. Der folgende Code produziert darum ein Paar Compiler-Fehler:

public class StaticCat {

  private int alter = 12;

  public int getAlter(){
      return alter;
  }

    static{
        System.out.println(alter); // Fehler 1
        getAlter(); // Fehler 2
    }
}

In Zeile 10 versucht der static-Initializer auf die Instanzvariable alter und in Zeile 11 auf die Instanz-Methode getAlter() zuzugreifen. Da der statische Initializer aber objektunabhängig ist, kann dies nicht funktionieren, da alter und getAlter()an die Existenz eines Objekts gebunden sind. Mit einem Instanz-Initializer andererseits würde dieser Code einwandfrei funktionieren.

Werbung

Java lernen

Werde zum Java Profi!

PHP Lernen

Lerne serverbasierte Programmierung

JavaScript lernen

Skille dein Webcoding

FALCONBYTE.NET

Handmade with 🖤️

© 2018-2023 Stefan E. Heller

Impressum | Datenschutz | Changelog

Falconbyte Youtube Falconbyte GitHub facebook programmieren lernen twitter programmieren lernen discord programmieren lernen