– Cześć, Amigo! Teraz opowiem Ci, jak tworzone są obiekty.

– Co w tym takiego skomplikowanego, wujku Raszi? Piszesz new i nazwę klasy, wskazujesz właściwy konstruktor i gotowe!

– To prawda. Ale co się dzieje wewnątrz obiektu, kiedy to robisz?

– Co się tam dzieje?

– Już wyjaśniam: obiekt jest tworzony w kilku etapach.

1) Wpierw do wszystkich zmiennych składowych klasy przydzielana jest pamięć.

2) Następnie inicjalizowana jest klasa bazowa.

3) Później wszystkim zmiennym przypisywane są wartości (o ile zostały one określone).

4) W końcu wywoływany jest konstruktor.

– To nie wygląda na trudne: najpierw zmienne, potem konstruktor.

– Zobaczmy, jak to działa na przykładzie z dwiema klasami:

Kod Opis
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; ←-
 }
}
Zadeklarowano dwie klasy: Pet(pet) i Cat(cat).

W klasie Cat widzimy jawne odwołanie do konstruktora klasy bazowej.
To powinno być zawsze w pierwszej linii w konstruktorze.

A oto, co dzieje się po przydzieleniu pamięci:
18 – wywołanie konstruktora klasy bazowej.
3, 4 – inicjalizacja zmiennych w Pet.
8, 9 – wykonanie kodu w konstruktorze Pet.

Następnie rozpocznie się inicjalizacja klasy Cat.
14 – inicjalizacja zmiennych w Cat.
19 – wykonanie kodu w konstruktorze Cat.

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

– Nie do końca rozumiem. Dlaczego to takie skomplikowane?

– Tak naprawdę nic w tym trudnego, jeśli wiesz, co się tam naprawdę dzieje:

Jeśli dana klasa nie posiada żadnych konstruktorów, zostanie on utworzony automatycznie.

Konstruktor domyślny
class Cat
{
 int x = 5;
 int y = 5;
}
class Cat
{
 int x = 5;
 int y = 5;
 public Cat() 
 {
 }
}

Jeśli nie wywołasz konstruktora klasy bazowej, zostanie on wywołany automatycznie.

Wywołanie konstruktora klasy bazowej
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();
 }
}

Zmienne składowe są inicjalizowane w konstruktorze.

Inicjalizacja zmiennych składowych
class Cat
{
 int x = 5;
 int y = 5;
}
class Cat
{
 int x;
 int y;
 public Cat()
 {
  super();
  this.x = 5;
  this.y = 5;
  }
}
Co się dzieje naprawdę
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)
 {
  //wywołanie konstruktora klasy bazowej
  super();
  //inicjalizacja zmiennych
  this.x = 5;
  this.y = 5;
  this.weight = 10;
  //wykonanie kodu konstruktora
  this.x = x;
  this.y = y;
 }
}
class Cat extends Pet
{
 int tailLength;
 int age;
 Cat(int x, int y, int age)
 {
  //wywołanie konstruktora klasy bazowej
   super(x, y);
  //inicjalizacja zmiennych
  this.tailLength = 8;
  //wykonanie kodu konstruktora
  this.age = age;
 }
}

– Teraz jest to o wiele bardziej zrozumiałe: najpierw klasa bazowa, potem zmienne poza konstruktorem, a następnie kod konstruktora.

– Dobra robota, Amigo! To wszystko!