Wie funktioniert “final int i” innerhalb einer Java for-Schleife?

Lesezeit: 3 Minuten

Ich war überrascht zu sehen, dass das folgende Java-Code-Snippet kompiliert und ausgeführt wurde:

for(final int i : listOfNumbers) {
     System.out.println(i);
}

wobei listOfNumbers ein Array von ganzen Zahlen ist.

Ich dachte, Schlusserklärungen würden nur einmal vergeben. Erstellt der Compiler ein Integer-Objekt und ändert es, worauf es verweist?

Stellen Sie sich vor, dass die Kurzschrift ungefähr so ​​aussieht:

for (Iterator<Integer> iter = listOfNumbers.iterator(); iter.hasNext(); )
{
    final int i = iter.next();
    {
        System.out.println(i);
    }
}

Benutzer-Avatar
Rückfall

Siehe @TravisG für eine Erläuterung der betroffenen Scoping-Regeln. Der einzige Grund, warum Sie eine Endschleifenvariable wie diese verwenden würden, ist, wenn Sie sie in einer anonymen inneren Klasse schließen müssten.

import java.util.Arrays;
import java.util.List;

public class FinalLoop {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(new Integer[] { 0,1,2,3,4 });
        Runnable[] runs = new Runnable[list.size()];

        for (final int i : list) {
            runs[i] = new Runnable() {
                    public void run() {
                        System.out.printf("Printing number %d\n", i);
                    }
                };
        }

        for (Runnable run : runs) {
            run.run();
        }
    }
}

Die Schleifenvariable ist nicht im Gültigkeitsbereich des Runnable, wenn sie ausgeführt wird, sondern nur, wenn sie instanziiert wird. Ohne das final Schlüsselwort wäre die Schleifenvariable für das Runnable nicht sichtbar, wenn es schließlich ausgeführt wird. Selbst wenn es so wäre, wäre es derselbe Wert für alle Runnables.

Übrigens, vor ungefähr 10 Jahren haben Sie vielleicht eine sehr kleine Geschwindigkeitsverbesserung bei der Verwendung von final für eine lokale Variable gesehen (in einigen seltenen Fällen); das ist schon lange nicht mehr so. Nun ist der einzige Grund, final zu verwenden, Ihnen zu erlauben, einen lexikalischen Abschluss wie diesen zu verwenden.

Als Antwort auf @mafutrct:

Wenn Sie Code schreiben, tun Sie dies für zwei Zielgruppen. Der erste ist der Computer, der, solange er syntaktisch korrekt ist, mit allen Entscheidungen zufrieden sein wird, die Sie treffen. Die zweite ist für einen zukünftigen Leser (häufig Sie selbst), hier ist das Ziel, die „Absicht“ des Codes zu kommunizieren, ohne die „Funktion“ des Codes zu verschleiern. Sprachmerkmale sollten idiomatisch mit so wenigen Interpretationen wie möglich verwendet werden, um Mehrdeutigkeiten zu reduzieren.

Im Fall der Schleifenvariablen könnte die Verwendung von final verwendet werden, um eines von zwei Dingen zu kommunizieren: Einzelzuweisung; oder Schließung. Ein einfacher Scan der Schleife wird Ihnen sagen, ob die Schleifenvariable neu zugewiesen wurde; Aufgrund der Verschachtelung zweier Ausführungspfade beim Erstellen einer Closure kann jedoch leicht übersehen werden, dass die Closure die Variable erfassen soll. Es sei denn natürlich, Sie verwenden final immer nur, um eine Erfassungsabsicht anzugeben, an welcher Stelle dem Leser klar wird, was passiert.

  • Oder um die Absicht zu dokumentieren, diese Variable nicht neu zuweisbar zu machen.

    – Sean Patrick Floyd

    12. Oktober 2010 um 4:52 Uhr

  • Nein! Wenn Sie dies tun, haben Sie jetzt zwei semantische Bedeutungen für dieselbe Syntax – man hat echte Verwendungen; der andere ist überflüssig, es sei denn, Ihre Methode ist viel viel zu lang. Verwenden Sie final nur, um anzugeben, dass Sie beabsichtigen, den Parameter zu schließen, noch nie um eine Einzelaufgabe anzuzeigen.

    – Rückfall

    15. Oktober 2010 um 4:09 Uhr


  • @Recurse Das klingt vernünftig. Könntest du aber den Grund dahinter erklären? Ich bin mir nicht sicher, ob ich die Gründe verstehe

    – mafu

    27. November 2012 um 14:10 Uhr

1061940cookie-checkWie funktioniert “final int i” innerhalb einer Java for-Schleife?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy