10.11.18 4963 Views 5

credit: ©RS-Studios

Java Tutorial #14

Java Initializer

Vielleicht werden Sie Initializer nur selten in Programmcodes finden und Sie sollten sie auch sparsam einsetzen, da sie den Code unübersichtlich machen können. Trotzdem sind sie ein Konzept, das wir für einen umfassenden Umgang mit der Objektorientierung beherrschen sollten.

Falconbyte unterstüzen

Betrieb und Pflege von Falconbyte brauchen viel Zeit und Geld. Um dir auch weiterhin hochwertigen Content anbieten zu können, kannst du uns sehr gerne mit einem kleinen "Trinkgeld" unterstützen.

Thema in Kurzform

  • Initializer sind spezielle Methoden ohne Methodenkopf.
  • Der Code von Instanz-Initializern wird unmitelbar bei der Objekt-Erzeugung aufgerufen.
  • static-Initializer werden mit dem Schlüsselwort static eingeleitet und werden bei der ersten Benutzung der Klasse automatisch aufgerufen.

    Inhaltsverzeichnis

  1. Instanz-Initializer
  2. static-Initializer
  3. Übungen

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.

Übungen

einfach

Was ist der Unterschied zwischen einem Instanz-Initializer und einem static-Initializer?

Lösung ein-/ausblenden

mittel

Was gibt der folgende Code auf der Konsole aus?

public class Uebung {

    private String a = "Programming";
    private static String b = "Java";
    private String c = "Code";

    public Uebung(){
        System.out.println(a);
    }

    static{
        System.out.println(b);
    }

    {
        System.out.println(c);
    }

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

Lösung ein-/ausblenden

schwer

Was wird auf der Konsole ausgegeben?

public class Diamond {

    public static int solution;

    public Diamond(){
        solution++;
    }

    { solution += 4; }

    static
    { solution += 2; }
    { solution -= 3; }

}
public class DiamondEngage {

    public static void main(String[] args){
        System.out.print(Diamond.solution);
        System.out.print(Diamond.solution);
        new Diamond();
        new Diamond();
        new Diamond();
        System.out.print(Diamond.solution);

    }
}

A. Der Code ist fehlerhaft!
B. 123
C. 228
D. -1-114
E. 004

Lösung ein-/ausblenden

Der Konstruktor

Was ist eigentlich ein Konstruktor?

Objekte vergleichen

Was ist der Unterschied zwischen == und equals()?

toString() Methode

Lernen Sie hier, wie Sie die toString() Methode korrekt einsetzen

FALCONBYTE.NET

Handmade with 🖤️

© 2018-2022 Stefan E. Heller

Impressum | Datenschutz | Changelog

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