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.
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:
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.
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.
Java Basics
[Java einrichten] [Variablen] [Primitive Datentypen] [Operatoren] [if else] [switch-case] [Arrays] [Schleifen]
Objektorientierung
[Einstieg] [Variablen ] [Konstruktor] [Methoden] [Rekursion] [Statische Member] [Initializer] [Pass-by-value] [Objektsammlungen] [Objektinteraktion] [Objekte löschen]
Klassenbibliothek
[Allgemeines] [String ] [Math] [Wrapper] [Scanner] [java.util.Arrays] [Date-Time-API]
Vererbung
[Einstieg Vererbung] [Konstruktoren bei Vererbung ] [Der protected Zugriffsmodifikator] [Abstrakte Klassen und Methoden] [Polymorphie in Java] [Typumwandlung] [Die Klasse Object] [Die toString()-Methode] [Objekte vergleichen] [Was ist ein Interface?]