Apakah ada bedanya jika saya mendeklarasikan variabel di dalam atau di luar loop di Java? [Tutup]

13

Kemungkinan Gandakan:
Di mana Anda mendeklarasikan variabel? Bagian atas suatu metode atau ketika Anda membutuhkannya?

Apakah ada bedanya jika saya mendeklarasikan variabel di dalam atau di luar loop di Java?

Apakah ini

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

sama dengan ini (sehubungan dengan penggunaan memori)?

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

Dan bagaimana jika variabel sementara misalnya ArrayList?

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

EDIT: dengan javap -csaya mendapat output berikut

Variabel di luar loop:

  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  

Variabel di dalam loop:

  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        

Dan untuk yang berminat, kode ini:

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

menghasilkan ini:

  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   

Tetapi optimasi terjadi saat runtime. Apakah ada cara untuk melihat kode yang dioptimalkan? (Maaf untuk EDIT yang panjang)

Puckl
sumber
1
Saya senang Anda benar-benar melihat pembongkaran dan berharap itu mengajarkan Anda sesuatu. Saya berharap seseorang dengan pengalaman Java yang sebenarnya akan menjawab pertanyaan terakhir Anda tentang kode yang dioptimalkan, tetapi mungkin Anda dapat memposting bagian spesifik itu di Stackoverflow - sepertinya ini adalah pertanyaan yang sangat konkret.
Joris Timmermans
Ya, saya akan mencoba untuk mendapatkan kode yang dioptimalkan. (Pertanyaannya sedikit berubah, saya menanyakan hal itu dengan kode yang dioptimalkan dalam pengeditan)
Puckl
Tautan rusak pada Duplikat. Saatnya menjadikan pertanyaan ini Asli.
Zon

Jawaban:

4

Jawaban umum untuk sebagian besar pertanyaan ini adalah "mengapa Anda tidak mencobanya dan mencari tahu?". Di Jawa Anda mungkin bisa melihat bytecode yang dihasilkan (saya percaya alat ini disebut javap), untuk melihat apa perbedaan dalam kode byte antara dua cara mendeklarasikan variabel.

Melakukannya seperti itu adalah pengalaman belajar yang lebih baik bagi Anda, karena lain kali Anda mengalami masalah optimisasi, Anda dapat menggunakan alat yang sama untuk memverifikasi bahwa kompiler melakukan apa yang Anda harapkan - ini akan membantu Anda menghindari pengubahan kode yang tidak perlu. gaya ketika pengoptimal baik-baik saja sendiri, atau menemukan tweak aktual ketika Anda benar-benar membutuhkan sedikit kinerja terakhir.

Joris Timmermans
sumber
3

Jawaban singkat: tidak. Sudah ada pertanyaan serupa di suatu tempat di situs ini. Tidak ada perbedaan penting sesuai bytecode yang dihasilkan. Mendeklarasikan mereka saat dibutuhkan menghasilkan lebih sedikit baris kode

Inilah jawaban yang diterima: /software//a/56590/43451

Kemoda
sumber
Bagaimana dengan kinerja ketika Anda membuat objek baru di dalam loop, yang bisa dibuat sekali saja?
Bubblewrap
3
Dalam hal ini jelas ada penalti kinerja dan memori. Tetapi tidak demikian halnya dalam pertanyaan op
Kemoda
1
Tautan rusak.
Zon
1

Pada tingkat variabel individu tidak ada perbedaan yang signifikan dalam efisiensi, tetapi jika Anda memiliki fungsi dengan 1000 loop dan 1000 variabel (apalagi gaya buruk tersirat) mungkin ada perbedaan sistemik karena semua umur semua variabel akan menjadi sama, bukannya tumpang tindih. Hal ini dapat memengaruhi hal-hal seperti ukuran tumpukan dan kemampuan pengumpul sampah untuk membersihkan variabel yang tetap hidup lebih lama dari yang diperlukan.

Selain itu, gaya yang jauh lebih baik untuk memberikan variabel ruang lingkup sekecil mungkin. Ini mencegah kecelakaan.

ddyer
sumber
Ini tidak benar - di tingkat JVM, tidak ada ruang lingkup terbatas untuk variabel lokal.
Michael Borgwardt
maksud Anda jika saya menulis untuk (int i = ..) 1000 kali, akan ada 1000 variabel yang berbeda pada stack ketika saya keluar dari fungsi?
ddyer
menurut artima.com/insidejvm/ed2/jvm8.html "Misalnya, jika dua variabel lokal memiliki cakupan terbatas yang tidak tumpang tindih, seperti variabel lokal i dan j di Example3b, kompiler bebas menggunakan entri array yang sama untuk kedua variabel. "Dan itu hanya masuk akal, kompiler bebas untuk mengoptimalkan ukuran frame stack dengan cara ini.
ddyer
1
Poin bagus; tetapi jika kita berbicara tentang optimisasi kompiler, kompiler dapat dengan mudah menggunakan kembali entri variabel lokal untuk variabel yang memiliki cakupan leksikal yang tumpang tindih tetapi tidak digunakan secara tumpang tindih.
Michael Borgwardt