-
s = new String("xyz"); มีการสร้าง String Object จำนวนเท่าใด สองวัตถุ อันหนึ่งคือ "xyx" และอีกอันคือวัตถุอ้างอิงที่ชี้ไปที่ "xyx"
String s="Hello";int i=3; s=i+s; นิพจน์นี้ถูกต้องหรือไม่ ใน java ระบบจะแจ้งว่าประเภทข้อมูลไม่ตรงกัน เนื่องจาก string เป็นคลาส! วิธีการที่ถูกต้อง: s+="3" หรือ s+='3' หรือ s+=(char)i;
เราจะแนะนำวิธีอื่นในการสร้างวัตถุ String - ข้อความที่อยู่ในเครื่องหมายคำพูด วิธีนี้เป็นลักษณะเฉพาะของ String และแตกต่างจากวิธีใหม่อย่างมาก
มีพูลสตริงใน JAVA Virtual Machine (JVM) ซึ่งจัดเก็บอ็อบเจ็กต์ String จำนวนมากและสามารถแชร์ได้ ดังนั้นจึงปรับปรุงประสิทธิภาพ สตริง a="abc"; เมื่อบรรทัดของโค้ดนี้ถูกดำเนินการ เครื่องเสมือน JAVA จะค้นหาพูลสตริงก่อนเพื่อดูว่ามีออบเจ็กต์ที่มีค่า "abc" อยู่แล้วหรือไม่ พื้นฐานสำหรับการตัดสินคือคลาส String เท่ากับ (Object obj) ค่าที่ส่งคืนของวิธีการ ถ้ามี จะไม่มีการสร้างออบเจ็กต์ใหม่ และการอ้างอิงไปยังออบเจ็กต์ที่มีอยู่จะถูกส่งกลับโดยตรง หากไม่มี ออบเจ็กต์จะถูกสร้างขึ้นก่อน จากนั้นจึงเพิ่มลงในพูลสตริง จากนั้นการอ้างอิงจะถูกส่งคืน
การสร้างอ็อบเจ็กต์สตริง: เนื่องจากมีการใช้อ็อบเจ็กต์สตริงอย่างกว้างขวาง [เป็นอ็อบเจ็กต์ โดยทั่วไปแล้ว อ็อบเจ็กต์จะจัดสรรหน่วยความจำในฮีปเสมอ] ใน Java เพื่อประหยัดพื้นที่หน่วยความจำและเวลาทำงาน [เช่น เมื่อเปรียบเทียบสตริง == ดีกว่าเท่ากับ()] ตัวอักษรสตริงทั้งหมดจะถูกใส่ลงในพูลตามตัวอักษรในระหว่างขั้นตอนการคอมไพล์ และพูลตามตัวอักษรรันไทม์จะกลายเป็นส่วนหนึ่งของพูลคงที่ ข้อดีของพูลตามตัวอักษรคือค่าคงที่สตริงเดียวกันทั้งหมดในพูลจะถูกรวมเข้าด้วยกัน และครอบครองเพียงช่องว่างเดียวเท่านั้น เรารู้ว่าสำหรับตัวแปรอ้างอิงสองตัว ให้ใช้ == เพื่อพิจารณาว่าค่า [references] เท่ากันหรือไม่ นั่นคือตัวแปรชี้ไปที่วัตถุเดียวกัน:
ตอนนี้ดูที่คำสั่ง String s = new String("abc"); ที่นี่ "abc" เองเป็นอ็อบเจ็กต์ในพูล และเมื่อ new String() ถูกดำเนินการที่รันไทม์ สำเนาของอ็อบเจ็กต์ในพูลจะถูกวางไว้ ในฮีป และส่งมอบการอ้างอิงของวัตถุนี้ในฮีปให้กับ s โอเค คำสั่งนี้สร้างวัตถุ 2 สตริง
String s1 = new String("abc") ;String s2 = new String("abc") ;if( s1 == s2 ){ //คำสั่งที่จะไม่ถูกดำเนินการ}
// มีการสร้าง String Objects กี่ชิ้น [สามอันในพูลและอีกสองอันในฮีป -
เฉพาะออบเจ็กต์ใหม่ที่สร้างขึ้นโดยการเชื่อมต่อ "+" ระหว่างออบเจ็กต์สตริงที่สร้างขึ้นโดยใช้เครื่องหมายคำพูดเพื่อรวมข้อความเท่านั้นที่จะถูกเพิ่มลงในพูลสตริง สำหรับนิพจน์การเชื่อมต่อ "+" ทั้งหมดที่มีออบเจ็กต์ใหม่ที่สร้างขึ้นในวิธีการใหม่ (รวมถึงค่าว่าง) ออบเจ็กต์ใหม่ที่สร้างขึ้นจะไม่ถูกเพิ่มลงในพูลสตริง
1.== หมายความว่าอ้างอิงมาจากวัตถุเดียวกัน และเท่ากับ() หมายความว่าค่าเท่ากัน
String str1 = "abc"; วัตถุอ้างอิงอยู่บนสแต็ก (หรือพูลสตริง)
String str1 =new String ("abc"); วัตถุอ้างอิงอยู่ในหน่วยความจำ/ฮีป
2.String str1 = "string";
String str3 = "str"; บนสแต็ก
String str4 = "ing"; บนสแต็ก
String str2 = str3+str4; ในฮีป เนื่องจากฟังก์ชันของเครื่องหมาย + คือการส่งคืนอ็อบเจ็กต์ String ที่สร้างขึ้นใหม่แทนการค้นหาค่าสตริงบนสแต็ก หากเป็น String str2 = "str"+"ing"; ผลลัพธ์สุดท้ายจะอยู่ที่สแต็ก str1==str2 เป็นจริง
แต่มีสถานการณ์หนึ่งที่เรียกร้องความสนใจจากเรา โปรดดูรหัสด้านล่าง:
StringStaticTest ระดับสาธารณะ {
สตริงสุดท้ายแบบคงที่สาธารณะ A = "ab"; // ค่าคงที่ A
สาธารณะคงที่สุดท้าย String B = "cd"; // ค่าคงที่ B
โมฆะคงที่สาธารณะ main (String [] args) {
String s = A + B; // เริ่มต้น s โดยเชื่อมต่อค่าคงที่ทั้งสองด้วย +
สตริง t = "abcd";
ถ้า (s == t) {
System.out.println("s เท่ากับ t เป็นวัตถุเดียวกัน");
} อื่น {
System.out.println("s ไม่เท่ากับ t ไม่ใช่วัตถุเดียวกัน");
-
-
-
ผลลัพธ์ของการรันโค้ดนี้จะเป็นดังนี้:
s เท่ากับ t, พวกมันคือวัตถุเดียวกัน
เหตุผลก็คือในตัวอย่างข้างต้น A และ B เป็นค่าคงที่และค่าของพวกมันได้รับการแก้ไข ดังนั้นค่าของ s จึงได้รับการแก้ไขเช่นกัน และจะถูกกำหนดเมื่อมีการคอมไพล์คลาส กล่าวคือ: String s=A+B; เทียบเท่ากับ: String s="ab"+"cd";
ฉันขอเปลี่ยนตัวอย่างข้างต้นเล็กน้อยแล้วดูว่าเกิดอะไรขึ้น:
StringStaticTest ระดับสาธารณะ {
สตริงสุดท้ายแบบคงที่สาธารณะ A; // ค่าคงที่ A
สตริงสุดท้ายแบบคงที่สาธารณะ B; // ค่าคงที่ B
คงที่ {
อ = "เอบี";
B = "ซีดี";
-
โมฆะคงที่สาธารณะ main (String [] args) {
// เริ่มต้น s โดยเชื่อมต่อค่าคงที่ทั้งสองด้วย +
สตริง s = A + B;
สตริง t = "abcd";
ถ้า (s == t) {
System.out.println("s เท่ากับ t เป็นวัตถุเดียวกัน");
} อื่น {
System.out.println("s ไม่เท่ากับ t ไม่ใช่วัตถุเดียวกัน");
-
-
-
ผลลัพธ์ของการดำเนินการคือ:
s ไม่เท่ากับ t พวกมันไม่ใช่วัตถุเดียวกัน
เพิ่งทำการเปลี่ยนแปลงเล็กน้อย และผลลัพธ์ก็ตรงกันข้ามกับตัวอย่างในตอนนี้เลย มาวิเคราะห์กันอีกครั้ง แม้ว่า A และ B จะถูกกำหนดให้เป็นค่าคงที่ (สามารถกำหนดได้เพียงครั้งเดียว) แต่ก็ไม่ได้ถูกกำหนดทันที ก่อนที่จะคำนวณค่า s ตัวแปรทั้งหมดจะถูกกำหนดค่าเมื่อใดและค่าใดที่ได้รับมอบหมาย ดังนั้น A และ B จึงมีพฤติกรรมเหมือนตัวแปรก่อนที่จะกำหนดค่า ดังนั้นไม่สามารถระบุได้ในเวลาคอมไพล์ แต่สามารถสร้างได้เฉพาะตอนรันไทม์เท่านั้น
สุดท้ายนี้ เรามาพูดถึงการจัดเก็บออบเจ็กต์ String ใน JAVA Virtual Machine (JVM) และความสัมพันธ์ระหว่าง string pool กับฮีปและสแต็ก ก่อนอื่นมาทบทวนความแตกต่างระหว่างฮีปและสแต็ค:
สแต็ก: บันทึกประเภทพื้นฐาน (หรือประเภทในตัว) เป็นหลัก (ถ่าน, ไบต์, สั้น, int, ยาว, ลอย, สองเท่า, บูลีน) และการอ้างอิงวัตถุสามารถแชร์ได้ และความเร็วของมันนั้นเร็วกว่าเท่านั้น กอง.
ฮีป: ใช้เพื่อจัดเก็บวัตถุ
เมื่อเราดูซอร์สโค้ดของคลาส String เราจะพบว่ามีแอตทริบิวต์ value ซึ่งเก็บค่าของวัตถุ String ประเภทคือ char[] ซึ่งแสดงว่าสตริงเป็นลำดับของอักขระด้วย เมื่อดำเนินการ String a="abc"; เครื่องเสมือน JAVA จะสร้างค่าถ่านสามค่า 'a', 'b' และ 'c' ในสแต็ก จากนั้นสร้างวัตถุ String ในฮีป ค่าของมัน (value ) คืออาร์เรย์ของค่าถ่านสามค่าที่เพิ่งสร้างบนสแต็ก {'a', 'b', 'c'} ในที่สุด ออบเจ็กต์ String ที่สร้างขึ้นใหม่จะถูกเพิ่มลงในพูลสตริง
หากเรารันโค้ด String b=new String("abc"); เนื่องจาก "abc" ถูกสร้างขึ้นและบันทึกในพูลสตริง เครื่องเสมือน JAVA จะสร้างเฉพาะออบเจ็กต์ String ใหม่ในฮีป แต่ value คือค่าประเภทถ่านสามค่า 'a', 'b' และ 'c' ที่สร้างขึ้นบนสแต็กเมื่อมีการดำเนินการโค้ดบรรทัดก่อนหน้า
ณ จุดนี้ เราค่อนข้างชัดเจนแล้วเกี่ยวกับคำถามที่ว่าทำไม String str=new String("abc") ที่ถูกยกขึ้นตอนต้นของบทความนี้จึงสร้างอ็อบเจ็กต์สองตัวขึ้นมา
บทความนี้มาจากบล็อก CSDN โปรดระบุแหล่งที่มาเมื่อพิมพ์ซ้ำ: http://blog.csdn.net/yakihappy/archive/2009/03/10/3977169.aspx
บทความนี้มาจากบล็อก CSDN โปรดระบุแหล่งที่มาเมื่อพิมพ์ซ้ำ: http://blog.csdn.net/Foxalien/archive/2009/12/18/5029470.aspx
-