2016-06-18 9 views
3

Betrachten wir eine for Schleife mit einem Zähler:Ist der Gültigkeitsbereich einer Variablen, die in einer for-Schleifen-Deklaration initialisiert wird, tatsächlich mehr als nur den Gültigkeitsbereich zu blockieren?

for (int i = 0; i < 100; i++ /* `i` is visible here */) { 
    /* `i` is visible here */ 
} 
/* `i` not visible here */ 

Alles ist gut. We say that i has "block" scope.

Warum sind Variablen, die innerhalb der for-Schleife deklariert werden, unter i++ nicht zugänglich?

Zum Beispiel, warum ist j nicht im Bereich hier, wenn es auch "Block" Bereich hat und in einem Zeitraum, der vor i += j ist, deklariert wurde?

for (int i = 0; i < 100; i += j /* only `i` is visible here */) { 
    int j = 1; 
    /* `i` and `j` are visible here */ 
} 
/* `i` and `j` are not visible here */ 

Ich habe viele Fragen in Bezug auf den Umfang der i, gesehen, aber nicht in Bezug auf den Umfang der j innerhalb der for Schleife Klammern. Bedeutet das, dass es technisch einen anderen Bereich gibt, über den niemand spricht, der "For-Loop-Deklarationsumfang" ist? Wenn ja, interessiert mich, wie dieser Bereich in Spezifikationen wie Java oder C# definiert ist und in welchem ​​Umfang er von Programmierern allgemein bezeichnet wird.

Bearbeiten: Ja, ich verstehe, dass ich die Schleife als for (int j, i = 0; i < 100; i += j) deklarieren kann, aber das zeigt immer noch, dass for Schleifendeklarationen einen höheren Bereich als ihre geschweiften Klammern haben.

Antwort

2

Der Gesicht Grund für diese, dass JLS 6.3 gibt den Scoping auf diese Weise:

Der Umfang einer lokalen Variablen in dem ForInit Teil einer Basis für Anweisung deklarierten (§14.14.1) umfasst alle folgenden:

  • Seine eigene initializer
  • Weitergehende Deklaratoren nach rechts in den ForInit Teil der for-Anweisung
  • Die Expression und forUpdate Teile der for-Anweisung
  • Die

die "enthaltene Aussage" die for Körper Statement enthalten. Für Variablen, die in einem for-Body definiert sind, gibt es keine speziellen Bereichsregeln. Die normalen Regeln gelten. (Sie sind auch in JLS 6.3.)


Die Gründe für diese Sprache Design gehören (Ich denke,) folgendes:

  • Es wäre für die Lesbarkeit schlecht sein, wenn Sie schauen musste innerhalb des Schleifenkörpers für Variablen deklariert dort .
  • Die Logik zur Bestimmung, ob die in der Schleife deklarierte Variable definitiv initialisiert wurde, wäre schwer zu spezifizieren und für Programmierer schwer zu verstehen. Beispiel:

    for (i = 1; i < 10; i = i + j) { 
        int j; 
        if (i > 3) { 
         j = 42; 
        } 
        // do stuff 
    } 
    

1 - Die wahren Gründe würden nur an die Designer von C bekannt sein ... zurück in den 1970er Jahren. Ich bezweifle ernsthaft, dass die Java-Designer überhaupt daran gedacht haben, so etwas zu tun.

2 - Es ist schlimm genug, dass etwas im Schleifenkörper eine Schleifenvariable ändern könnte. :-(

+0

Großartig! Dies ist genau das, was ich gesucht habe. Hat dieses Scoping einen Namen? Wie "Block" Anwendungsbereich tut? – 4castle

+1

Nicht das ist mir bewusst. Aber ich denke nicht, dass es auch einen braucht. Es ist nur das Standard-Scoping von for-Schleifen in C-abgeleiteten Sprachen. –

+0

Großartig! Lassen Sie mich wissen, dass ich nur im Sinne des Lernens frage. Wenn ich wirklich mein Inkrement am Ende der for-Schleife verwenden möchte, lasse ich den ForUpdate-Teil einfach leer und setze ihn am Ende des Schleifenkörpers. Das war faszinierend, aber :) – 4castle

-1

Die Variable J wird vor der Deklaration/Initialisierung referenziert. Wenn die erste Zeitschleife ausgeführt wird, hat JVM keinen Verweis darauf.

Sie haben die Variable j innerhalb der Schleife initialisiert.

Ich hoffe, dass dies Ihre Frage löscht.

+0

Das beantwortet meine Frage nicht :( – 4castle

0

Der erste Bereich beginnt mit void main {} nach anderen inneren Blöcken mit Ihrem for-Schleifenbereich, und alle mit diesem ersten Block deklarierten Variablen sind für alle inneren Blöcke des Bereichs sichtbar, und müssen wir die Variable vor der Verwendung deklarieren Es (in Ihrem Fall Variable j) Sie Variable innerhalb der Schleife verwendet, ohne es deklariert, so ist es nicht möglich, es vor Deklarationen zu verwenden, und unser Cursor bei for for loop wegen der von oben nach unten Ansatz Zeile für Zeile zuerst kam es zu überprüfen Variable sind deklariert oder nicht?

+0

Meine Frage geht nicht so sehr um "was", sondern vielmehr darum, wo/wie dies von Dokumentation und der Community definiert wird. Es gibt viele Male Wenn Compiler keine Dateien von oben nach unten lesen, zum Beispiel beim Lesen von Methodendeklarationen in einer Klasse, ist die Reihenfolge egal – 4castle

0

Eine sehr interessante Frage. Sie heben einen sehr guten Punkt hervor, dass j sichtbar sein sollte, wenn Sie es aus der Laufzeitperspektive betrachten, da der Inkrementausdruck nach der Iteration aufgerufen wird.

Aber von Compiler-Perspektive, wenn es liest die for-Schleife-Anweisung d. H. (int i = 0; i < 100; i += j), würde erwarten, dass j bereits deklariert werden.

Ich denke, Sie können sagen, ich habe eine zusätzliche Aussage Bereich im Vergleich zu den Block Umfang, die beide i und j haben.

+0

Danke! "Aussage" Bereich ist neu für mich. Es fühlt sich an wie der Compiler intern verschieben sollte 'i + = j 'Teil bis zum Ende der' for'-Schleife vor dem Versuch, es zu analysieren, aber ich denke, das ist nicht, wie es funktioniert Gibt es irgendwelche Spezifikationen oder Ressourcen für "Aussage" Geltungsbereich? – 4castle

+0

Schauen Sie sich Stephen's Antwort für Spezifikation :) –