Liệu nó có tạo ra sự khác biệt nếu tôi khai báo các biến bên trong hoặc bên ngoài một vòng lặp trong Java không? [đóng cửa]


13

Có thể trùng lặp:
Bạn khai báo biến ở đâu? Đầu của một phương pháp hoặc khi bạn cần chúng?

Liệu nó có tạo ra sự khác biệt nếu tôi khai báo các biến bên trong hoặc bên ngoài một vòng lặp trong Java không?

Có phải đây là

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

bằng cái này (đối với việc sử dụng bộ nhớ)?

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

Và nếu biến tạm thời là ví dụ về ArrayList thì sao?

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

EDIT: với javap -ctôi đã nhận được đầu ra sau đây

Biến ngoài vòng lặp:

  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  

Biến trong vòng lặp:

  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        

Và cho những người quan tâm, mã này:

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

sản xuất này:

  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   

Nhưng tối ưu hóa xảy ra trong thời gian chạy sau đó. Có cách nào để xem mã được tối ưu hóa không? (Xin lỗi vì EDIT dài)


1
Tôi hài lòng bạn thực sự nhìn vào sự tháo gỡ và hy vọng nó đã dạy cho bạn một cái gì đó. Tôi đã hy vọng ai đó có kinh nghiệm thực tế về Java sẽ trả lời câu hỏi cuối cùng của bạn về mã được tối ưu hóa, nhưng có lẽ bạn có thể đăng phần cụ thể đó lên Stackoverflow - đây có vẻ là một câu hỏi rất cụ thể.
Joris Timmermans

Có, tôi sẽ cố gắng để có được mã tối ưu hóa. (Câu hỏi đã thay đổi một chút, tôi đã hỏi điều đó với mã được tối ưu hóa trong chỉnh sửa)
Puckl

Liên kết bị hỏng trên trùng lặp. Đã đến lúc biến câu hỏi này thành Bản gốc.
Zon

Câu trả lời:


4

Câu trả lời chung cho hầu hết các câu hỏi này là "tại sao bạn không thử và tìm hiểu?". Trong Java, có lẽ bạn có thể xem mã byte được tạo (tôi tin rằng công cụ này được gọi là javap), để xem sự khác biệt trong mã byte là gì giữa hai cách khai báo biến.

Làm như vậy là một trải nghiệm học tập tốt hơn cho bạn, vì lần tới khi bạn gặp phải vấn đề tối ưu hóa, bạn có thể sử dụng cùng một công cụ để xác minh rằng trình biên dịch đang làm những gì bạn đang mong đợi - nó sẽ giúp bạn tránh thay đổi mã hóa một cách không cần thiết phong cách khi trình tối ưu hóa tự hoạt động tốt hoặc tìm các tinh chỉnh thực tế khi bạn thực sự cần chút hiệu suất cuối cùng đó.


3

Câu trả lời ngắn gọn: không. Có những câu hỏi tương tự ở đâu đó trên trang web này. Không có sự khác biệt đáng chú ý theo mã byte được tạo. Khai báo chúng khi cần sẽ tạo ra ít dòng mã hơn

Đây là câu trả lời được chấp nhận: /software//a/56590/43451


Còn hiệu suất khi bạn tạo một đối tượng mới bên trong vòng lặp, điều đó chỉ có thể được tạo ra một lần thì sao?
Bubblewrap

3
Trong trường hợp này rõ ràng là có hiệu suất và hình phạt bộ nhớ. Nhưng nó không hoàn toàn là trường hợp trong câu hỏi của op
Kemoda

1
Liên kết bị hỏng.
Zon

1

Ở cấp độ của biến riêng lẻ, không có sự khác biệt đáng kể về hiệu quả, nhưng nếu bạn có một hàm với 1000 vòng lặp và 1000 biến số (đừng bận tâm đến kiểu xấu ngụ ý) có thể có sự khác biệt về hệ thống bởi vì tất cả cuộc sống của tất cả các biến sẽ là giống nhau thay vì chồng chéo. Điều này có thể ảnh hưởng đến những thứ như kích thước ngăn xếp và khả năng của người thu gom rác để dọn sạch các biến đang được duy trì lâu hơn mức cần thiết.

Ngoài ra, đó là phong cách tốt hơn nhiều để cung cấp cho các biến phạm vi nhỏ nhất có thể. Nó ngăn ngừa tai nạn.


Điều này không đúng - ở cấp độ JVM, không có thứ gọi là phạm vi giới hạn cho các biến cục bộ.
Michael Borgwardt

bạn có nghĩa là nếu tôi viết cho (int i = ..) 1000 lần, sẽ có 1000 biến khác nhau trên ngăn xếp khi tôi thoát khỏi hàm?
ddyer

theo artima.com/insidejvm/ed2/jvm8.html "Ví dụ: nếu hai biến cục bộ có phạm vi giới hạn không trùng nhau, chẳng hạn như biến cục bộ i và j trong Ví dụ3b, trình biên dịch có thể sử dụng cùng một mục nhập mảng cho cả hai biến. "Và điều đó chỉ có ý nghĩa, trình biên dịch có thể tự do tối ưu hóa kích thước của khung ngăn xếp theo cách này.
ddyer

1
Điểm tốt; nhưng nếu chúng ta đang nói về tối ưu hóa trình biên dịch, trình biên dịch có thể dễ dàng sử dụng lại các mục nhập biến cục bộ cho các biến có phạm vi từ vựng chồng chéo nhưng không được sử dụng theo cách chồng chéo.
Michael Borgwardt
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.