Macht es einen Unterschied, ob ich in Java Variablen innerhalb oder außerhalb einer Schleife deklariere? [geschlossen]


13

Mögliches Duplikat:
Wo deklarieren Sie Variablen? Die Spitze einer Methode oder wann brauchen Sie sie?

Macht es einen Unterschied, ob ich in Java Variablen innerhalb oder außerhalb einer Schleife deklariere?

Ist das

for(int i = 0; i < 1000; i++) {
   int temp = doSomething();
   someMethod(temp);
}

gleich diesem (in Bezug auf die Speichernutzung)?

int temp = 0;
for(int i = 0; i < 1000; i++) {
   temp = doSomething();
   someMethod(temp);
}

Und was ist, wenn die temporäre Variable zum Beispiel eine ArrayList ist?

for(int i = 0; i < 1000; i++) {
   ArrayList<Integer> array = new ArrayList<Integer>();
   fillArray(array);
   // do something with the array
}

BEARBEITEN: mit habe javap -cich folgende ausgabe bekommen

Variable außerhalb der Schleife:

  public static void main(java.lang.String[]);
    Code:
       0: iconst_0      
       1: istore_1      
       2: iconst_0      
       3: istore_2      
       4: iload_2       
       5: sipush        1000
       8: if_icmpge     25
      11: invokestatic  #2                  // Method doSomething:()I
      14: istore_1      
      15: iload_1       
      16: invokestatic  #3                  // Method someMethod:(I)V
      19: iinc          2, 1
      22: goto          4
      25: return  

Variable innerhalb der Schleife:

  public static void main(java.lang.String[]);
    Code:
       0: iconst_0      
       1: istore_1      
       2: iload_1       
       3: sipush        1000
       6: if_icmpge     23
       9: invokestatic  #2                  // Method doSomething:()I
      12: istore_2      
      13: iload_2       
      14: invokestatic  #3                  // Method someMethod:(I)V
      17: iinc          1, 1
      20: goto          2
      23: return        

Und für die Interessenten dieser Code:

public class Test3 {
    public static void main(String[] args) {
        for(int i = 0; i< 1000; i++) {
            someMethod(doSomething());
        }   
    }
    private static int doSomething() {
        return 1;
    }
    private static void someMethod(int temp) {
        temp++;
    }
}

produziert dies:

  public static void main(java.lang.String[]);
    Code:
       0: iconst_0      
       1: istore_1      
       2: iload_1       
       3: sipush        1000
       6: if_icmpge     21
       9: invokestatic  #2                  // Method doSomething:()I
      12: invokestatic  #3                  // Method someMethod:(I)V
      15: iinc          1, 1
      18: goto          2
      21: return   

Die Optimierung erfolgt dann aber zur Laufzeit. Gibt es eine Möglichkeit, den optimierten Code zu betrachten? (Sorry für die lange BEARBEITUNG)


1
Ich freue mich, dass Sie sich die Demontage angeschaut haben und hoffe, sie hat Ihnen etwas beigebracht. Ich hatte gehofft, dass jemand mit tatsächlicher Java-Erfahrung Ihre letzte Frage zum optimierten Code beantworten würde, aber vielleicht können Sie diesen bestimmten Teil auf Stackoverflow veröffentlichen - es scheint eine sehr konkrete Frage zu sein.
Joris Timmermans

Ja, ich werde versuchen, den optimierten Code zu bekommen. (Die Frage hat sich ein wenig geändert, ich habe die Sache mit dem optimierten Code in der Bearbeitung
gefragt

Fehlerhafter Link bei Duplizieren. Es ist Zeit, diese Frage zu einem Original zu machen.
Zon

Antworten:


4

Die allgemeine Antwort auf die meisten dieser Fragen sollte lauten: "Warum probieren Sie es nicht aus und finden es heraus?". In Java könnten Sie sich wahrscheinlich den generierten Bytecode ansehen (ich glaube, das Tool heißt javap), um zu sehen, was der Unterschied im Bytecode zwischen diesen beiden Arten der Deklaration der Variablen ist.

Dies zu tun ist eine bessere Lernerfahrung für Sie, da Sie das nächste Mal, wenn Sie auf ein Optimierungsproblem stoßen, mit demselben Tool überprüfen können, ob der Compiler das tut, was Sie erwarten - es hilft Ihnen, unnötige Änderungen an Ihrer Codierung zu vermeiden Stil, wenn der Optimierer von sich aus gut abschneidet, oder tatsächliche Optimierungen, wenn Sie wirklich das letzte bisschen Leistung brauchen.


3

Kurze Antwort: nein. Irgendwo auf dieser Site gab es bereits ähnliche Fragen. Es gibt keinen nennenswerten Unterschied zum generierten Bytecode. Wenn Sie sie bei Bedarf deklarieren, werden weniger Codezeilen erstellt

Hier ist die akzeptierte Antwort: /software//a/56590/43451


Was ist mit der Leistung, wenn Sie ein neues Objekt innerhalb der Schleife erstellen, das genauso gut nur einmal erstellt werden kann?
Luftpolsterfolie

3
In diesem Fall gibt es offensichtlich Leistung und Gedächtnisstrafe. In der Frage des
Einsatzes

1
Verbindung ist unterbrochen.
Zon

1

Auf der Ebene der einzelnen Variablen gibt es keinen signifikanten Unterschied in der Effizienz, aber wenn Sie eine Funktion mit 1000 Schleifen und 1000 Variablen hätten (ungeachtet des implizierten schlechten Stils), könnten systembedingte Unterschiede auftreten, da alle Leben aller Variablen gleich wären das gleiche statt überlappen. Dies kann Auswirkungen auf die Stapelgröße und die Fähigkeit des Garbage Collectors haben, die Variablen zu bereinigen, die länger als nötig am Leben gehalten wurden.

Es ist auch viel besser, Variablen den kleinstmöglichen Umfang zu geben. Es beugt Unfällen vor.


Dies ist nicht der Fall - auf JVM-Ebene gibt es keinen begrenzten Bereich für lokale Variablen.
Michael Borgwardt

Meinen Sie, dass wenn ich 1000 mal für (int i = ..) schreibe, es 1000 verschiedene Variablen auf dem Stapel geben wird, wenn ich die Funktion verlasse?
Ddyer

Laut artima.com/insidejvm/ed2/jvm8.html "Wenn beispielsweise zwei lokale Variablen begrenzte Bereiche haben, die sich nicht überlappen, wie die lokalen Variablen i und j in Beispiel3b, können Compiler den gleichen Array-Eintrag verwenden für beide Variablen. "Und das ist nur sinnvoll, Compiler können die Größe des Stack-Frames auf diese Weise optimieren.
Ddyer

1
Guter Punkt; aber wenn wir reden über Compiler - Optimierungen, der Compiler kann fast so leicht Wiederverwendung lokale Variable Einträge für Variablen , die lexikalischen Gültigkeitsbereich haben überlappende sind aber nicht verwendet überlappend.
Michael Borgwardt
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.