Infos zum Artikel
Kategorie | Java |
Autor | Stefan |
Datum | 10.11.2018 |
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.
- Instanz-Initializer
- static-Initializer
- Übungen
Inhaltsverzeichnis
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"-Initialzer 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?
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();
}
}
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