# Reihenfolge der Initialisierungen eines Objekts



## ernst (1. Nov 2007)

Hallo allerseits,
In welcher Reighenfolge wird in Java ein Objekt initialisiert?
Die Attribute eines Objekt können z.B. bestehen aus:
- einfachen DatentypenAttributen
- Objekten (mit dem Datentyp einer Klasse)
außerdem kann es Attribute (und Methoden) erben 

Beispiel: (komplettes Programm unten)
class Sohn extends Vater{  
	public int s=Do.myprint("S0");
	Freundin myf=new Freundin(123);

	public Sohn(int pv, int ps){
		super(ps);		
		s = ps;
	}
}

class MyTest extends MyVater {
  private i = 12;
  MyKlasse myk;
}

Frage:
I) Was passiert, wenn z.B. ein Objekt dieser Klasse Sohn angelegt
wird.
In welcher Reihenfolge werden die Attribute dieser Klasse wie initialisiert?

Meine Meinung ist folgende:
1)
1.1)  Standardinitialisierung der Attribute der Klasse Sohn, also 
s = 0 und
myf = null

1.2) Initialisierung der Oberklasse
1.2.1) 
Standardinitialisierung der Attribute der Klasse Vater, also 
v=0
1.2.2)Initialisierung der Attribute der Klasse Vater, also 
v=Do.myprint("V0");
das bedeutet konkret: v=1
1.2.3) Aufruf des Konstruktors der Klasse Vater

1.3) Initialisierung der Attribute der Klasse Sohn, also 
s=Do.myprint("S0");
myf=new Freundin(123);

1.4) Aufruf des Konstruktors der Klasse Sohn


2) Gibt es einen Link zu einer Website, in dem genau beschrieben wird,
wie dies allgemein funktioniert?


-----------------------------------------------------------------------

public class MainInitReihenfolge1 {
	public static void main(String[] args){
		Sohn myS= new Sohn(10,20);
	}
}

class Sohn extends Vater{  
	public int s=Do.myprint("S0");
	Freundin myf=new Freundin(123);

	public Sohn(int pv, int ps){
		super(ps);		
		s = ps;
	}
}

class Vater{  
	public int v=Do.myprint("V0");

	public Vater(int pv){
		System.out.println("Konstruktor Vater v="+v);		
		v=pv;
		System.out.println("Konstruktor Vater v="+v);		
	}
}

class Freundin{
	public int f=Do.myprint("F0");;

	public Freundin(int pf){
		System.out.println("Konstruktor Freundin f="+f);		
		f=pf;
		System.out.println("Konstruktor Freundin f="+f);		
	}
}

class Do{
	public static int myprint(String ps){
		System.out.println(ps);
		return 1;
	}
}

-----------------------------------------------------------------------

mfg
Ernst


----------



## Wildcard (1. Nov 2007)

Zuerst alles was static ist, dann die Attribute der Superklassen, dann die Konstruktoren der Superklassen, dann die Attribute der Klasse, dann der Konstruktor.
Solltest du aus einem anderen Grund als Neugier fragen:
Programmlogik darf sich niemals auf Initialisierungsreihenfolgen verlassen.


----------



## ernst (1. Nov 2007)

Wildcard hat gesagt.:
			
		

> Zuerst alles was static ist, dann die Attribute der Superklassen, dann die Konstruktoren der Superklassen, dann die Attribute der Klasse, dann der Konstruktor.
> Solltest du aus einem anderen Grund als Neugier fragen:
> Programmlogik darf sich niemals auf Initialisierungsreihenfolgen verlassen.


-----------------
1)
Was wird zuerst gemacht:
die Standardinsitialisierung (s = 0 und myf = null) oder die
Initialisierung, die der Programmierer veranlasst (public int s=Do.myprint("S0");
Freundin myf=new Freundin(123))?

2)
mit static meinst du die Klassenvariablen.
Diese werden zuerst initialisiert. Gut, aber was wird zuerst gemacht:
die Standardinsitialisierung oder die
Initialisierung, die der Programmierer veranlasst ?


mfg
Ernst


----------



## Wildcard (1. Nov 2007)

Alles wird zunächst auf defaults gesetzt (0, null, false)


----------



## ernst (1. Nov 2007)

Programmlogik darf sich niemals auf Initialisierungsreihenfolgen verlassen.[/quote]
------------------
Warum?
Wenn es einen Algorithmus gibt, der die Reihenfolge der Initialisierungen festlegt, dann kann man sich doch darauf verlassen, oder?


----------



## Wildcard (1. Nov 2007)

Hast du das etwa vor?
Das ist eine sehr zuverlässige Art schwer zu findende Fehler zu produzieren  :toll: 
Was schwebt dir vor?


----------



## André Uhres (1. Nov 2007)

Man unterscheidet Statische Initialisierung und Instanzinitialisierung.
Jede dieser zwei Arten hat wieder drei Unterarten:
- einfache Initialisierung
- Initialisierung durch Aufruf einer statischen Methode
- Initialisierungsblock
Letzterer ist möglichst zu vermeiden, der Code wird sonst schnell unübersichtlich.

Statische Initialisierungen werden zuerst ausgeführt.
Die weitere Reihenfolge innerhalb der zwei Hauptarten ist einfach die des Erscheinens im Code der Klasse.
Nach der Initialisierung wird der Konstruktor aufgerufen.

Insbesondere auf die Reihenfolge von statischen Initialisierungen sollte man sich aber nicht verlassen.
Durch Verschachtelungen kann es zu unerwarteten Ergebnissen kommen, die schwer nachvollziehbar sind.


----------



## ernst (2. Nov 2007)

>Man unterscheidet Statische Initialisierung und Instanzinitialisierung.
>
Was ist eine statische Iniialisierung, was ist eine Instanzinitialisierung?
>
>Jede dieser zwei Arten hat wieder drei Unterarten:
>- einfache Initialisierung
>
was ist eine einfache Initialisierung
>- Initialisierung durch Aufruf einer statischen Methode
>
ist das folgende Beispiel von mir eine "Initialisierung durch Aufruf einer statischen Methode"?
public int s=Do.myprint("S0");
>
>- Initialisierungsblock
>
was ist ein Initialisierungsblock?
>
>Letzterer ist möglichst zu vermeiden, der Code wird sonst schnell unübersichtlich.
>
Ich habe die Begriffe Standardinitialsierung (s = 0 und myf = null) und Initialiserung (public int s=Do.myprint("S0"); 
Freundin myf=new Freundin(123)) verwendet.
Wie nennst du diese Begriffe in deiner Terminologie?
>
>Statische Initialisierungen werden zuerst ausgeführt.
>Die weitere Reihenfolge innerhalb der zwei Hauptarten ist einfach die des Erscheinens im Code der Klasse.
>Nach der Initialisierung wird der Konstruktor aufgerufen.
>
Kannst du mir ein Beispiel geben, in dem alle diese von dir aufgezählten Möglichkeiten dargestellt werden?
Ich habe schon einige Bücher durchgeschaut, aber in keinem gibt es ein Beispiel, in dem alle Möglichkeiten dargestellt werden.

mfg
Ernst


----------



## ernst (2. Nov 2007)

Wildcard hat gesagt.:
			
		

> Alles wird zunächst auf defaults gesetzt (0, null, false)


----------
Kannst du das präzisieren, vielleicht in einem umfassenden Beispiel?

mfg
Ernst


----------



## ernst (2. Nov 2007)

>Hast du das etwa vor?
>
Nein
>Das ist eine sehr zuverlässige Art schwer zu findende Fehler zu produzieren  :toll: 
>
Warum?
>
>Was schwebt dir vor?[/quote]
>
Mir schwebt nichts vor.
Ich will nur das Verfahren wissen, wie in Java die Initialisierungsreihenfolge festgelegt ist.

mfg
Ernst


----------



## André Uhres (2. Nov 2007)

>Man unterscheidet Statische Initialisierung und Instanzinitialisierung.
>
Was ist eine statische Iniialisierung, was ist eine Instanzinitialisierung?
statisch (keyword: "static"): wird beim Laden der Klasse vom ClassLoader initialisiert.
Statische Variablen gelten für alle Instanzen der Klasse, Instanzvariablen nur für eine bestimmte Instanz der Klasse.
>
>Jede dieser zwei Arten hat wieder drei Unterarten:
>- einfache Initialisierung
>
was ist eine einfache Initialisierung
Das ist eine einfache Zuweisung eines Konstanten Wertes: 
*private String x = "blabla";*

>- Initialisierung durch Aufruf einer statischen Methode
>
ist das folgende Beispiel von mir eine "Initialisierung durch Aufruf einer statischen Methode"?
public int s=Do.myprint("S0");
Richtig. Anderes Beispiel: 
*private String version = System.getProperty("java.version");*

>
>- Initialisierungsblock
>
was ist ein Initialisierungsblock?
Beispiel:
*private String version;
{
   version = System.getProperty("java.version");
}*
zwischen den geschweiften Klammern ist der Initialisierungsblock, dort kann, ähnlich wie in einer Methode,
auch mehr als eine Anweisungen stehen.
>
>Letzterer ist möglichst zu vermeiden, der Code wird sonst schnell unübersichtlich.
>
Ich habe die Begriffe Standardinitialsierung (s = 0 und myf = null) und Initialiserung (public int s=Do.myprint("S0"); 
Freundin myf=new Freundin(123)) verwendet.
Wie nennst du diese Begriffe in deiner Terminologie?
"Standardinitialsierung"  ist bei mir ausgeklammert, da es ja nicht explizit gecodet wird und man
von vornherein davon ausgehen kann, dass eine nicht initialisierte Variable immer den Standardwert hat.
>
>Statische Initialisierungen werden zuerst ausgeführt.
>Die weitere Reihenfolge innerhalb der zwei Hauptarten ist einfach die des Erscheinens im Code der Klasse.
>Nach der Initialisierung wird der Konstruktor aufgerufen.
>
Kannst du mir ein Beispiel geben, in dem alle diese von dir aufgezählten Möglichkeiten dargestellt werden?
Ich habe schon einige Bücher durchgeschaut, aber in keinem gibt es ein Beispiel, in dem alle Möglichkeiten dargestellt werden.
Gut, 3 Beispiele hab ich ja eben angeführt. Hier ist das in statischer Form:

*private static String x = "blabla";

private static String version = System.getProperty("java.version");

private static String version;
static
{
   version = System.getProperty("java.version");
}*


----------



## ernst (2. Nov 2007)

Ich habe deine Erläuterungen wie folgt zusammengefasst:
I)
Eine statische Initialisierung wird durch den Bezeichner static charakterisiert, eine nicht statische Initialisierung ohne den Bezeichner static.
Es gibt bei statischen bzw. nicht statischen Initialisierungen folgende Möglichkeiten:
a) einfache Initialisierung 
b) Initialisierung durch Aufruf einer statischen Methode
c) Initialisierung durch Initialisierungsblock (statischer bzw. nicht statischer Initialisierungsblock)

II)
Reihenfolge der Initialisierungen:
1) Alle Attribute aller Objekte sind prinzipiell mit den Standardwerten vorbelegt.
2) Alle statischen Attribute der Oberklasse des Objekts werden in der Reihenfolge ihres Auftauchens in der Klassenimplementierung initialisiert.
3) Alle statischen Attribute des Objekts werden in der Reihenfolge ihres Auftauchens in der Klassenimplementierung initialisiert.
4) Alle nicht statischen Attribute der Oberklasse des Objekts werden in der Reihenfolge ihres Auftauchens in der Klassenimplementierung initialisiert.
5) Der Konstruktor der Oberklasse wird aufgerufen.
6) Alle nicht statischen Attribute des Objekts werden in der Reihenfolge ihres Auftauchens in der Klassenimplementierung initialisiert.
7) Der Konstruktor der Klasse wird aufgerufen.

Ist das korrekt?

III)
Im Buch Java ist auch eine Insel (http://bequiet.homeip.net/i/bequiet...sel06_005.htm#Rxx747java06005040001E61F0271D3)  
wird behauptet, dass wenn ein Attribut wie z.B. int i=1 mit 1 initialisiert wird, dies vom Compiler als Programmcode in den Konstruktor mit aufgenommen wird. Stimmt das?
Wie ist das dann aber bei statischen Attributen(d.h. Klassenvariablen)?


IV)
Ein Beispielprogramm von mir:

```
public class MainInitReihenfolge2 {
	public static void main(String[] args){
		Sohn myS= new Sohn(10,20);
		StaticTest.f();
		StaticTest.f();		
		StaticTest myx=new StaticTest();

	}
}

class Sohn extends Vater{
	//einfache Initialisierung	
	public int s1=52;
	//Initialisierung durch Aufruf einer statischen Methode 
	public int s2=Do.myprint("S2");
	public static int s3=Do.myprint("S3");	
	Freundin myf=new Freundin(123);

	//Initialisierung durch Initialisierungsblock	
	{
	System.out.println("Initialisierungsblock Sohn");		
	}
	
	
	public Sohn(int pv, int ps){
		super(ps);		
		s1 = ps;
		s2=13;
	}
}

class Vater{  
	//einfache Initialisierung	
	public int v1=53;	
	//Initialisierung durch Aufruf einer statischen Methode	
	public int v2=Do.myprint("V2");
	public static int v3=Do.myprint("V3");	

	//Initialisierung durch Initialisierungsblock	
	{
	System.out.println("Initialisierungsblock Vater");		
	}
	
	public Vater(int pv){
		System.out.println("Konstruktor Vater v="+v1);		
		v1=pv;
		v2=67;
		System.out.println("Konstruktor Vater v="+v1);		
	}
}

class Freundin{
	//einfache Initialisierung	
	public int f1=45;
	//Initialisierung durch Aufruf einer statischen Methode	
	public int f2=Do.myprint("F0");;

	//Initialisierung durch Initialisierungsblock	
	{
	System.out.println("Initialisierungsblock Freundin");		
	}
	
	
	public Freundin(int pf){
		System.out.println("Konstruktor Freundin f="+f1);		
		f1=pf;
		System.out.println("Konstruktor Freundin f="+f1);		
	}
}

class Do{
	public static int myprint(String ps){
		System.out.println(ps);
		return 1;
	}
}

class StaticTest{
	public int i=11;
	//Initialisierung durch statischen Initialisierungsblock	

	static 
	{
	System.out.println("Hallo Static Welt");		
	}
	
	{
	System.out.println("Hallo Nicht Static Welt");		
	}

	
	public static void f(){
	//public void f(){		
		System.out.println("Hallo ich bin f");		
	}
}
```

mfg
Ernst


----------



## André Uhres (3. Nov 2007)

II): Reihenfolge ist das korrekt.
III): Stimmt. 
Selbstverständlich gilt das nicht für statische Attribute, 
da diese beim Laden der Klasse initialisiert werden und nicht bei jeder Instanz.


----------



## ernst (3. Nov 2007)

André Uhres hat gesagt.:
			
		

> II): Reihenfolge ist das korrekt.
> III): Stimmt.
> Selbstverständlich gilt das nicht für statische Attribute,
> da diese beim Laden der Klasse initialisiert werden und nicht bei jeder Instanz.


--------------
Wenn wir gerade bei statischen Attributen (Klassenvariablen) sind:
Wann wird der statische Initialisierungsblock einer Klasse ausgeführt?
Er soll ausgeführt werden, so habe ich gelesen, wenn der Klassenlader  eine Klasse in die Laufzeitumgebung geladen hat.
Frage:
Wann wird diese in die Laufzeitumgebung geladen?
Spätestens doch dann, wenn über eine Methode auf eine Klassenvariable der Klasse zugegriffen wird. Ist das richtig?

mfg
Ernst


----------



## Leroy42 (3. Nov 2007)

Bevor hier alles durchgekaut wird, schau dir das entsprechende Kapitel
in der JLS : Java Language Specification an.
Das ist die ultimative Referenz.


----------



## André Uhres (3. Nov 2007)

Leroy42 hat gesagt.:
			
		

> ..Das ist die ultimative Referenz.


Die ist zwar in der Sprache von Shakespeare, aber viel langweiliger


----------



## Leroy42 (3. Nov 2007)

Ach komm!

Du hast nur kein Gefühl für die erlesene Wortwahl und Stilistik
dieser Prosa.


----------



## ernst (5. Nov 2007)

Leroy42 hat gesagt.:
			
		

> Bevor hier alles durchgekaut wird, schau dir das entsprechende Kapitel
> in der JLS : Java Language Specification an.
> Das ist die ultimative Referenz.


-------------------------------------------------
Danke für den Link. Da steht viel, so viel dass ich gar nicht alles davon verstehe, bzw. ich vielleicht für meine Frage gar nicht alles davon verstehen muss:

Mich interessiert nur, ob der statische Initialisierungsblock einer Klasse _spätestens_ dann ausgeführt wird, wenn 
über eine Methode auf eine Klassenvariable der Klasse zugegriffen wird. 
Ist das richtig? 

mfg
Ernst


----------

