Según la Java Sprachspezifikation, § 14.14.2 die Variable einer erweiterten for
Schleife muss für die Schleife lokal sein. Mit anderen Worten, dies lässt sich kompilieren:
for (State state : State.values()) {
// do something for each state
}
Dies ist jedoch nicht der Fall:
State state;
for (state: State.values()) {
// do something for each state
}
In der JLS wird keine Begründung für diese Wahl des Sprachdesigns gegeben. Ich kann verstehen, warum der Typname vorhanden sein muss, wenn die lokale Variable durch final
oder durch eine Anmerkung, aber ich verstehe nicht, warum der bloße Name einer an anderer Stelle deklarierten Variablen nicht zulässig ist. Kann mir jemand erklären, warum diese Einschränkung eingeführt wurde?
EDITAR
Mehrere Antworten scheinen darauf hinzudeuten, dass das, was außerhalb der Schleife geschieht, der Grund für die Gestaltung der Sprache auf diese Weise ist. Vielleicht wird eine genauere Betrachtung dessen, was die JLS sagt, klären, warum ich das nicht überzeugend finde. Betrachten Sie diese Schleife, in der State
ist eine Aufzählung:
for (State state : State.values()) {
// ...
}
State.values()
ist ein Array, so dass die Schleife laut JLS funktional identisch ist mit:
State[] a = State.values();
for (int i = 0; i < a.length; i++) {
State state = a[i];
// ...
}
Diese letzte Schleife hätte natürlich auch geschrieben werden können:
State state;
State[] a = State.values();
for (int i = 0; i < a.length; i++) {
state = a[i];
// ...
}
Konzeptionell könnte diese letzte (völlig legale) Schleife als funktionales Äquivalent der zweiten erweiterten Schleife verwendet werden for
Schleife (die sich nicht kompilieren lässt).
Ähnlich ist es, wenn stateList
es un Iterable<State>
(nicht ein Array), diese Schleife:
for (State state : stateList) {
// ...
}
ist funktionell identisch mit:
for (Iterator<State> iterator = stateList.iterator(); iterator.hasNext(); ) {
State state = iterator.next();
// ...
}
Wie zuvor, diese letzte Schleife geschrieben werden können:
State state;
for (Iterator<State> iterator = stateList.iterator(); iterator.hasNext(); ) {
state = iterator.next();
// ...
}
Auch hier gilt könnte wurden als funktionales Äquivalent zu den (illegalen) verwendet:
State state;
for (state : stateList) {
// ...
}
In jedem Fall wird beim Verlassen der Schleife der Wert von state
ist vollkommen klar definiert (wenn auch vielleicht nutzlos). Genau wie bei der regulären Schleife kann auch eine erweiterte for
Schleife mit einem bloßen Variablennamen, der nicht definiert wurde (z. B. die Zeile State state;
fehlte oder außerhalb des Geltungsbereichs lag) könnte zur Kompilierzeit abgefangen werden. Wo liegt also aus Sicht des Sprachdesigns das Problem? Warum haben die Sprachentwickler dieses Konstrukt verboten?