Fa differenza se dichiaro variabili all'interno o all'esterno di un ciclo in Java? [chiuso]

11

Fa differenza se dichiaro variabili all'interno o all'esterno di un ciclo in Java?

È questo

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

uguale a questo (rispetto all'utilizzo della memoria)?

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

E se la variabile temporanea fosse ad esempio un ArrayList?

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

EDIT: con javap -c ho ottenuto il seguente output

Variabile all'esterno del ciclo:

  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  

Variabile all'interno del ciclo:

  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        

E per gli interessati, questo codice:

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++;
    }
}

produce questo:

  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   

Allora l'ottimizzazione avviene in fase di esecuzione. C'è un modo per guardare il codice ottimizzato? (Scusa per il lungo EDIT)

    
posta Puckl 08.10.2012 - 11:29
fonte

3 risposte

4

La risposta comune alla maggior parte di queste domande dovrebbe essere "perché non provi e scopri?". In Java potresti probabilmente dare un'occhiata al codice byte generato (credo che lo strumento sia chiamato javap), per vedere quale sia la differenza nel codice byte tra questi due modi di dichiarare la variabile.

Farlo è un'esperienza di apprendimento migliore per te, perché la prossima volta che ti imbatti in un problema di ottimizzazione puoi utilizzare lo stesso strumento per verificare che il compilatore stia facendo quello che ti aspetti - ti aiuterà a evitare inutilmente cambia il tuo stile di codifica quando l'ottimizzatore funziona bene da solo, o trova modifiche effettive quando hai davvero bisogno dell'ultimo bit di prestazioni.

    
risposta data 08.10.2012 - 12:01
fonte
3

Risposta breve: no. C'erano già domande simili da qualche parte su questo sito. Non c'è alcuna differenza notevole secondo il codice byte generato. Dichiarandoli quando necessario produce meno righe di codice

Ecco la risposta accettata: link

    
risposta data 08.10.2012 - 11:33
fonte
1

A livello della singola variabile non vi è alcuna differenza significativa nell'efficienza, ma se tu avessi una funzione con 1000 cicli e 1000 variabili (non importa il cattivo stile implicito) potrebbero esserci differenze sistemiche perché tutte le vite di tutti i le variabili sarebbero le stesse invece che sovrapposte. Questo potrebbe influenzare cose come la dimensione dello stack e la capacità del garbage collector di ripulire le variabili che sono state mantenute in vita più a lungo del necessario.

Inoltre, è molto meglio dare alle variabili il più piccolo ambito possibile. Previene gli incidenti.

    
risposta data 08.10.2012 - 11:38
fonte

Leggi altre domande sui tag