Warum illegal forward reference bei Exemplarinitialisierer

Status
Nicht offen für weitere Antworten.

Schandro

Top Contributor
Hi,

Zitat aus der Insel Kapitel 6.5.8:
Der Programmcode der Exemplarinitialisierer wird an den Anfang aller Konstruktoren gesetzt. Objektvariablen wurden schon initialisiert.
warum wirft der Compiler für die Klasse E einen Compilerfehler ("illegal forward reference"), für E2 aber nicht? Es ist doch egal wo das Zeug im Code steht, der Compiler schreibt zuerst alle Membervariablendeklerationen in den Code jedes Konstruktors, danach alle Exemplarinitialisierer.
Code:
class E{

	public static void main(String[] args){
		new E();
		new E2();}

	{
		System.out.println(z);
	}

	S z = new S(1);
}

class E2{

	S z2 = new S(1);

	{
		System.out.println(z2);
	}
}


class S{
	public S(int i){
		System.out.println("new S("+i+")...");
	}
}
 
Keine Ahnung warum aber es geht so wie du es sagst nicht.
Hier wird es auch ohne Begründung erwähnt:
Insel hat gesagt.:
Wichtig ist abschließend zu sagen, dass vor dem Zugriff auf eine Objektvariable im Exemplar-initialisierer diese auch deklariert sein muss.
 
was soll denn für System.out.println(z) rauskommen?
das Objekt S(1) nicht, denn dann ginge folgendes nicht:

Code:
public class Test {

	public static void main(String[] args) {
		new E();
	}
}

class E {

	String b = "b";

	{
		b = "c";
	}

	String a = b;

	{
		System.out.println(a);
	}
}

// Ausgabe: c
die Deklarationszeile wird also nicht einfach vor alle {}-Konstruktoren verschoben sondern ist in den zeitlichen Ablauf integriert,

man könnte sich natürlich denken, dass nur die Variablendeklation nach vorne gezogen wird und die Zuweisung nicht, also etwa
Code:
String b;
String a;
{
  b = "b";
  b = "c";
  a = b;
}
dies mag vielleicht auch genau so sein,
aber in diesem Fall macht ein Zugriff auf noch nicht bekannte Variablen keinen Sinn, denn deren Wert kann nur null oder 'nicht initialisiert' sein, wozu darauf zugreifen?
insofern kann man ruhig auf diesen Zugriff verzichten und die Vorwärtsreferenz ganz verbieten, allein schon um das Paradoxon

String a = b;
String b = a;

einfach syntaktisch zu verhindern

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

so dachte ich zumindest ein paar Minuten,
mit folgendem Beispiel macht das aber auch nicht mehr ganz so viel Sinn:

Code:
	{
		a = "d"; // Zuweisung ist erlaubt?!
		System.out.println(a); // hier ist a wie zuvor nicht zugreifbar, 
		                       // wobei nun aber gewiss ein Inhalt ("d") vorhanden ist.. 
	}
	String a;
 
auch Inseln gehen unter 😉
wobei das vielleicht nur eine Frage der Interpretation ist
 
SlaterB hat gesagt.:
Code:
	{
		a = "d"; // Zuweisung ist erlaubt?!
		[ ... ]
	}
	String a;
Ist erlaubt, weil eine Zuweisung geschieht und nicht die Variable gelesen wird.
Solche Dinge liest man am besten in der JLS nach. War wohl doch nicht so falsch, dass einer meiner Profs immer so vehement aufs Spezifikationslesen verwiesen hat.
 
Siehts nur so aus, oder wird da im Konstruktor von "S" wirklich "new S(x)" aufgerufen? Tödliche (für's Prog natürlich) Rekursion würd' ich sagen, wenns nicht gequotet wär...
Der Fehler steckt hier wohl aber in den Zeilen 5 und 7... oder geht so ein Konstrukt?
Nach nochmaligem Überlegen:
Eclipse hat gesagt.:
Auf ein Feld kann erst dann verwiesen werden, wenn es definiert ist
in Zeile 8...
 
bei welchen code meinst du "zeile 5 und 7"?

das "new S()" im Konstruktor von S ist natürlich nur ein String...
 
Bei deinem... In Zeile 5 wird die Deklaration der Main-Methode beendet. Deswegen kommt in Zeile 7 ein Objekt-Initializer zustande, der "forward" auf eine noch nicht initialisierte Objekt-Variable zugreift. Wollte deswegen sagen, wenn man die beiden Klammern löscht gehts. Eine andere Lösung ist es, die Definition von "z" oberhalb des OIs zu platzieren.
 
jep, das ist bekannt^^
Es geht ja gar nicht darum meinen code kompilierbar zu machen, das könnt ich auch selber 😉
Es ging ja nur darum, das ich aus den Infos, die in der Insel standen, nicht wusste warum er der Compiler die Exception schmeisst
 
Status
Nicht offen für weitere Antworten.

Zurück
Oben