„Hallo Amigo! Jetzt möchte ich dir erzählen, wie Objekte erstellt werden.“

„Was ist daran so kompliziert, Onkel Ritschie? Man schreibt einfach new gefolgt vom Klassennamen, gibt den richtigen Konstruktor an und fertig!“

„Das stimmt. Aber was passiert innerhalb des Objekts, wenn du das tust?“

„Was passiert?“

„Das hier passiert: Das Objekt wird in mehreren Schritten erstellt.“

1) Zunächst wird Speicher für alle Member-Variablen der Klasse zugewiesen.

2) Dann wird die Basisklasse initialisiert.

3) Dann werden allen Variablen Werte zugewiesen, falls diese angegeben sind.

4) Schließlich wird der Konstruktor aufgerufen.

„Das sieht nicht sehr kompliziert aus: erst die Variablen, dann der Konstruktor.“

„Sehen wir uns mal an einem Beispiel mit zwei Klassen an, wie das funktioniert:“

Code Beschreibung
class Pet
{
 int x = 5, y = 5; ←-
 int weight = 10; ←-

 Pet(int x, int y)
 {
  this.x = x; ←-
  this.y = y; ←-
 }
}
class Cat extends Pet
{
 int tailLength = 8; ←-
 int age;
 Cat(int x, int y, int age)
 {
  super(x, y); ←-
  this.age = age; ←-
 }
}
Deklariere zwei Klassen: Pet(pet) und Cat(cat).

In der Cat-Klasse sehen wir einen expliziten Aufruf des Konstruktors der Basisklasse.
Er muss immer in der ersten Zeile des Konstruktors stehen.

Folgendes geschieht nach der Zuweisung des Speichers:
18 – Aufruf des Konstruktors der Basisklasse.
3, 4 – Variablen in Pet initialisieren.
8, 9 – Code im Pet-Konstruktor ausführen.

Dann beginnt die Initialisierung der Cat-Klasse.
14 – Variablen in Cat initialisieren.
19 – Code im Cat-Konstruktor ausführen.

public static void main(String[] args)
{
 Cat cat = new Cat (50, 50, 5);
}

„Das ist ein etwas verwirrend. Warum ist das so kompliziert?“

„Es ist eigentlich nicht so schwierig, wenn man weiß, was wirklich passiert:“

Wenn eine Klasse keine Konstruktoren besitzt, wird automatisch einer erzeugt.

Standardkonstruktor
class Cat
{
 int x = 5;
 int y = 5;
}
class Cat
{
 int x = 5;
 int y = 5;
 public Cat() 
 {
 }
}

Wenn du den Basisklassenkonstruktor nicht aufrufst, wird er automatisch aufgerufen.

Aufruf des Konstruktors der Basisklasse
class Pet
{
 public String name;
}
class Pet extends Object
{
 public String name;
 public Pet()
 {
  super();
 }
}
class Cat extends Pet
{
 int x = 5;
 int y = 5;
}
class Cat extends Pet
{
 int x = 5;
 int y = 5;
 public Cat()
 {
  super();
 }
}

Member-Variablen werden im Konstruktor initialisiert.

Initialisierung von Member-Variablen
class Cat
{
 int x = 5;
 int y = 5;
}
class Cat
{
 int x;
 int y;
 public Cat()
 {
  super();
  this.x = 5;
  this.y = 5;
  }
}
Das passiert tatsächlich
class Pet
{
 int x = 5, y = 5;
 int weight = 10;
 Pet(int x, int y)
 {
  this.x = x;
  this.y = y;
 }
}

class Cat extends Pet
{
 int tailLength = 8;
 int age;
 Cat(int x, int y, int age)
 {
  super(x, y);
  this.age = age;
 }
}
class Pet extends Object
{
 int x;
 int y;
 int weight;

 Pet(int x, int y)
 {
  //call of the base class's constructor
  super();
  //initialize variables
  this.x = 5;
  this.y = 5;
  this.weight = 10;
  //execute the constructor code
  this.x = x;
  this.y = y;
 }
}
class Cat extends Pet
{
 int tailLength;
 int age;
 Cat(int x, int y, int age)
 {
  //call of the base class's constructor
   super(x, y);
  //initialize variables
  this.tailLength = 8;
  //execute the constructor code
  this.age = age;
 }
}

„Jetzt verstehe ich es besser: zuerst die Basisklasse, dann Variablen außerhalb des Konstruktors, dann der Konstruktorcode.“

„Sehr gut, Amigo! Das war‘s!“