มันสร้างความแตกต่างถ้าฉันประกาศตัวแปรภายในหรือภายนอกวงใน Java? [ปิด]


13

ซ้ำได้:
คุณประกาศตัวแปรที่ไหน ด้านบนของวิธีการหรือเมื่อคุณต้องการ?

มันสร้างความแตกต่างถ้าฉันประกาศตัวแปรภายในหรือภายนอกวงใน Java?

นี่คือ

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

เท่ากับนี้ (เกี่ยวกับการใช้หน่วยความจำ)

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

และถ้าตัวแปรชั่วคราวเป็นตัวอย่างของ ArrayList

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

แก้ไข: javap -cฉันได้รับผลลัพธ์ต่อไปนี้

ตัวแปรนอกลูป:

  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  

ตัวแปรภายในลูป:

  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        

และสำหรับความสนใจรหัสนี้:

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

ผลิตสิ่งนี้:

  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   

แต่การเพิ่มประสิทธิภาพเกิดขึ้นที่รันไทม์แล้ว มีวิธีดูรหัสที่ได้รับการปรับปรุงหรือไม่? (ขออภัยสำหรับการแก้ไขที่ยาว)


1
ฉันดีใจที่คุณดูการถอดแยกชิ้นส่วนและหวังว่ามันจะสอนคุณบางอย่าง ฉันหวังว่าจะมีใครบางคนที่มีประสบการณ์เกี่ยวกับ Java ที่แท้จริงจะตอบคำถามสุดท้ายของคุณเกี่ยวกับรหัสที่ได้รับการปรับปรุง แต่บางทีคุณสามารถโพสต์ส่วนนั้น ๆ บน Stackoverflow ได้ - ดูเหมือนว่าจะเป็นคำถามที่เป็นรูปธรรมมาก
Joris Timmermans

ใช่ฉันจะพยายามรับรหัสที่ได้รับการปรับปรุง (คำถามที่เปลี่ยนแปลงเล็กน้อยผมถามสิ่งที่มีรหัสที่ดีที่สุดในการแก้ไข)
Puckl

ลิงก์ใช้งานไม่ได้เมื่อทำซ้ำ ได้เวลาตั้งคำถามนี้ให้เป็นฉบับดั้งเดิมแล้ว
Zon

คำตอบ:


4

คำตอบทั่วไปของคำถามเหล่านี้ส่วนใหญ่ควรเป็น "ทำไมคุณไม่ลองและค้นหาคำตอบ" ใน Java คุณอาจจะดูที่ bytecode ที่สร้างขึ้น (ฉันเชื่อว่าเครื่องมือนี้เรียกว่า javap) เพื่อดูความแตกต่างของโค้ดไบต์ระหว่างสองวิธีในการประกาศตัวแปร

การทำเช่นนี้เป็นประสบการณ์การเรียนรู้ที่ดีกว่าสำหรับคุณเพราะครั้งต่อไปที่คุณพบปัญหาการเพิ่มประสิทธิภาพคุณสามารถใช้เครื่องมือเดียวกันเพื่อตรวจสอบว่าคอมไพเลอร์กำลังทำสิ่งที่คุณคาดหวัง - มันจะช่วยให้คุณหลีกเลี่ยงการเปลี่ยนการเข้ารหัส สไตล์เมื่อเครื่องมือเพิ่มประสิทธิภาพทำงานได้ดีในตัวเองหรือค้นหาการปรับแต่งที่แท้จริงเมื่อคุณต้องการประสิทธิภาพสุดท้าย


3

คำตอบสั้น ๆ : ไม่ มีคำถามที่คล้ายกันอยู่ที่ไหนสักแห่งในเว็บไซต์นี้แล้ว ไม่มีความแตกต่างที่โดดเด่นตามรหัสที่สร้างขึ้น การประกาศพวกเขาเมื่อต้องการจะสร้างบรรทัดของรหัสน้อย

นี่คือคำตอบที่ได้รับการยอมรับ: /software//a/56590/43451


แล้วประสิทธิภาพเมื่อคุณสร้างวัตถุใหม่ภายในลูปก็สามารถสร้างได้เพียงครั้งเดียวเท่านั้น?
Bubblewrap

3
ในกรณีนี้เห็นได้ชัดว่ามีประสิทธิภาพและการลงโทษหน่วยความจำ แต่มันก็ไม่ได้เป็นอย่างนั้นในคำถามของ op
Kemoda

1
ลิงก์เสีย
Zon

1

ในระดับของตัวแปรแต่ละตัวไม่มีความแตกต่างอย่างมีนัยสำคัญในความมีประสิทธิภาพ แต่ถ้าคุณมีฟังก์ชั่นที่มี 1,000 ลูปและตัวแปร 1000 (ไม่คำนึงถึงสไตล์ที่ไม่ดีโดยนัย) อาจมีความแตกต่างของระบบเพราะชีวิตทั้งหมดของตัวแปรทั้งหมด เหมือนกันแทนที่จะซ้อนทับกัน สิ่งนี้อาจส่งผลกระทบต่อสิ่งต่าง ๆ เช่นขนาดสแต็คและความสามารถของตัวเก็บขยะในการล้างตัวแปรที่ยังคงมีชีวิตอยู่ได้นานเกินความจำเป็น

นอกจากนี้ยังมีสไตล์ที่ดีกว่ามากในการกำหนดขอบเขตที่เล็กที่สุดที่เป็นไปได้ให้กับตัวแปร ช่วยป้องกันอุบัติเหตุ


สิ่งนี้ไม่เป็นความจริง - ที่ระดับ JVM ไม่มีสิ่งเช่นขอบเขตที่ จำกัด สำหรับตัวแปรท้องถิ่น
Michael Borgwardt

คุณหมายถึงว่าถ้าฉันเขียน (int i = .. ) 1,000 ครั้งจะมีตัวแปรแตกต่างกัน 1,000 รายการในสแต็กเมื่อฉันออกจากฟังก์ชัน
ddyer

ตาม artima.com/insidejvm/ed2/jvm8.html "ตัวอย่างเช่นหากสองตัวแปรในตัวเครื่องมีขอบเขต จำกัด ที่ไม่ทับซ้อนกันเช่นตัวแปร i และ j ใน Local3b คอมไพเลอร์มีอิสระในการใช้รายการอาร์เรย์เดียวกัน สำหรับทั้งสองตัวแปร "และนั่นก็สมเหตุสมผลแล้วคอมไพเลอร์มีอิสระที่จะปรับขนาดของเฟรมสแต็กให้เหมาะสมที่สุดด้วยวิธีนี้
ddyer

1
จุดดี; แต่ถ้าเรากำลังพูดถึงการปรับให้เหมาะสมของคอมไพเลอร์คอมไพเลอร์สามารถนำรายการตัวแปรในเครื่องกลับมาใช้ซ้ำได้ง่ายสำหรับตัวแปรที่มีขอบเขตของคำศัพท์ที่ทับซ้อนกัน แต่ไม่ได้ใช้ในลักษณะที่ทับซ้อนกัน
Michael Borgwardt
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.