ไม่เลย
ประการแรกมีความแตกต่างเล็กน้อยในความหมาย ถ้าa
เป็นnull
แล้วa.concat(b)
พ่นNullPointerException
แต่a+=b
จะรักษาค่าเดิมของราวกับว่ามันเป็นa
null
นอกจากนี้concat()
วิธีการยอมรับเฉพาะString
ค่าในขณะที่+
ผู้ประกอบการจะแปลงอาร์กิวเมนต์เป็นเงียบ ๆ (ใช้toString()
วิธีการสำหรับวัตถุ) ดังนั้นconcat()
วิธีการที่เข้มงวดมากขึ้นในสิ่งที่มันยอมรับ
เพื่อดูภายใต้ประทุนเขียนชั้นเรียนง่ายๆด้วย a += b;
public class Concat {
String cat(String a, String b) {
a += b;
return a;
}
}
ตอนนี้ถอดแยกชิ้นส่วนด้วยjavap -c
(รวมอยู่ใน Sun JDK) คุณควรเห็นรายชื่อรวมถึง:
java.lang.String cat(java.lang.String, java.lang.String);
Code:
0: new #2; //class java/lang/StringBuilder
3: dup
4: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V
7: aload_1
8: invokevirtual #4; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
11: aload_2
12: invokevirtual #4; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
15: invokevirtual #5; //Method java/lang/StringBuilder.toString:()Ljava/lang/ String;
18: astore_1
19: aload_1
20: areturn
ดังนั้นจึงa += b
เท่ากับ
a = new StringBuilder()
.append(a)
.append(b)
.toString();
concat
วิธีการควรจะเร็ว อย่างไรก็ตามด้วยStringBuilder
วิธีการจำนวนมากที่ชนะอย่างน้อยในแง่ของประสิทธิภาพ
ซอร์สโค้ดของString
และStringBuilder
(และคลาสฐานแพ็กเกจส่วนตัว) มีอยู่ใน src.zip ของ Sun JDK คุณจะเห็นว่าคุณกำลังสร้างขึ้นแถวถ่าน (ปรับขนาดได้ตามความจำเป็น) String
แล้วทิ้งมันไปเมื่อคุณสร้างในขั้นตอนสุดท้าย ในทางปฏิบัติการจัดสรรหน่วยความจำนั้นรวดเร็วอย่างน่าประหลาดใจ
อัปเดต:ในฐานะที่เป็นบันทึกของ Pawel Adamski ประสิทธิภาพได้เปลี่ยนไปใน HotSpot ล่าสุด javac
ยังคงสร้างรหัสเดียวกันทั้งหมด แต่สูตรคอมไพเลอร์ bytecode การทดสอบอย่างง่ายล้มเหลวโดยสิ้นเชิงเนื่องจากรหัสทั้งหมดถูกโยนทิ้งไป การรวมSystem.identityHashCode
(ไม่String.hashCode
) แสดงStringBuffer
รหัสมีข้อได้เปรียบเล็กน้อย อาจมีการเปลี่ยนแปลงเมื่อมีการเปิดตัวอัพเดตครั้งถัดไปหรือหากคุณใช้ JVM อื่น จาก@lukaseder , รายการ intrinsics