Java String ฝึกงานคืออะไร?


234

คืออะไรString ฝึกงานใน Java เมื่อฉันควรจะใช้มันและทำไม ?



2
ถ้าเป็นเช่นString a = new String("abc"); String b = new String("abc"); นั้นa.intern() == b.intern()
Asanka Siriwardena

ตัวอย่างการฝึกงานของ Checkout String: algs4.cs.princeton.edu/12oop/MutableString.java.html
Ronak Poriya

ไม่String.intern()ขึ้นอยู่กับClassLoaderความหมาย, ทำ ClassLoader ที่แตกต่างกันของการสร้าง "แตกต่าง" Strings ก่อให้เกิดความแตกต่างกันinternหรือไม่?
AlikElzin-kilaka

1
@ AlikElzin-kilaka no classloaders ไม่เกี่ยวข้องทั้งหมดสำหรับการฝึกสตริง ในครั้งต่อไปที่คุณมีคำถามโปรดเปิดคำถามใหม่แทนที่จะโพสต์เป็นความคิดเห็นในคำถามอื่น
Holger

คำตอบ:


233

http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#intern ()

โดยพื้นฐานแล้วการทำ String.intern () ในชุดของสตริงจะทำให้แน่ใจว่าสตริงทั้งหมดที่มีเนื้อหาเดียวกันมีหน่วยความจำร่วมกันเหมือนกัน ดังนั้นหากคุณมีรายชื่อที่ปรากฏว่า 'john' ปรากฏขึ้น 1,000 ครั้งโดยการฝึกงานคุณจะมั่นใจได้ว่ามีเพียง 'john' ที่จัดสรรหน่วยความจำจริง

สิ่งนี้มีประโยชน์ในการลดความต้องการหน่วยความจำของโปรแกรมของคุณ แต่โปรดทราบว่า JVM เก็บรักษาแคชไว้ในพูลหน่วยความจำถาวรซึ่งโดยปกติจะมีขนาด จำกัด เมื่อเทียบกับฮีปดังนั้นคุณไม่ควรใช้ฝึกงานหากคุณไม่มีค่าซ้ำกันมากเกินไป


เพิ่มเติมเกี่ยวกับข้อ จำกัด ของหน่วยความจำของการใช้ฝึกงาน ()

ในมือข้างหนึ่งมันเป็นความจริงที่คุณสามารถลบ String ที่ซ้ำกันโดยการทำให้พวกเขาภายใน ปัญหาคือสตริงที่อยู่ภายในไปที่ Permanent Generation ซึ่งเป็นพื้นที่ของ JVM ที่สงวนไว้สำหรับวัตถุที่ไม่ใช่ผู้ใช้เช่นคลาสวิธีและวัตถุ JVM ภายในอื่น ๆ ขนาดของพื้นที่นี้มี จำกัด และมักจะมีขนาดเล็กกว่ากองมาก Calling intern () บน String มีผลในการย้ายออกจาก heap ไปเป็นรุ่นถาวรและคุณเสี่ยงต่อการใช้พื้นที่ PermGen

- จาก: http://www.codeinstructions.com/2009/01/busting-javalangstringintern-myths.html


จาก JDK 7 (ฉันหมายถึงใน HotSpot) มีบางอย่างเปลี่ยนไป

ใน JDK 7 สตริงการฝึกงานจะไม่ถูกจัดสรรในฮีป Java รุ่นถาวรอีกต่อไป แต่จะถูกจัดสรรในส่วนหลักของฮีป Java (ซึ่งรู้จักกันในชื่อรุ่นเยาว์และรุ่นเก่า) พร้อมกับวัตถุอื่นที่สร้างโดยแอปพลิเคชัน . การเปลี่ยนแปลงนี้จะส่งผลให้มีข้อมูลมากขึ้นที่อยู่ในฮีปหลักของ Java และข้อมูลน้อยลงในการสร้างถาวรและดังนั้นอาจต้องปรับขนาดฮีป แอปพลิเคชันส่วนใหญ่จะเห็นความแตกต่างเพียงเล็กน้อยในการใช้งานฮีปเนื่องจากการเปลี่ยนแปลงนี้ แต่แอปพลิเคชันขนาดใหญ่ที่โหลดคลาสจำนวนมากหรือใช้เมธอด String.intern () จำนวนมากจะเห็นความแตกต่างอย่างมีนัยสำคัญยิ่งขึ้น

- จากคุณสมบัติและการปรับปรุงของ Java SE 7

อัปเดต: สตริงภายในจะถูกเก็บไว้ในฮีปหลักจาก Java 7 เป็นต้นไป http://www.oracle.com/technetwork/java/javase/jdk7-relnotes-418459.html#jdk7changes


1
"แต่ต้องระวังว่า JVM เก็บรักษาแคชไว้ในพูลหน่วยความจำถาวรซึ่งมักจะมีขนาด จำกัด ...... "คุณอธิบายได้ไหม? ฉันไม่เข้าใจ
saplingPro

2
สตริง "ฝึกงาน" ถูกเก็บไว้ในขอบเขตหน่วยความจำพิเศษใน JVM โดยทั่วไปขอบเขตหน่วยความจำนี้จะมีขนาดคงที่และไม่ได้เป็นส่วนหนึ่งของ Java Heap ปกติที่จัดเก็บข้อมูลอื่น เนื่องจากขนาดคงที่อาจเกิดขึ้นได้ว่าขอบเขตหน่วยความจำถาวรนี้เต็มไปด้วยสตริงทั้งหมดของคุณซึ่งนำไปสู่ปัญหาที่น่าเกลียด (ไม่สามารถโหลดคลาสและสิ่งอื่น ๆ )
เชลโล่

@cello ดังนั้นมันคล้ายกับแคช?
saplingPro

8
@grassPro: ใช่มันเป็นชนิดของแคชหนึ่งที่ JVM ให้ไว้โดยกำเนิด เนื่องจากการผสานของ Sun / Oracle JVM และ JRockit วิศวกร JVM พยายามกำจัดขอบเขตหน่วยความจำถาวรใน JDK 8 ( openjdk.java.net/jeps/122 ) ดังนั้นจึงไม่มี ข้อ จำกัด ขนาดใด ๆ ในอนาคต
เชลโล่

9
ผู้เขียนโปรแกรมควรทราบด้วยว่าการฝึกงานในสายสามารถมีผลกระทบด้านความปลอดภัยได้ หากคุณมีข้อความที่ละเอียดอ่อนเช่นรหัสผ่านเป็นสตริงในหน่วยความจำข้อความนั้นอาจยังคงอยู่ในหน่วยความจำเป็นเวลานานแม้ว่าวัตถุสตริงที่แท้จริงจะมีความยาว GC'd ก็ตาม นั่นอาจเป็นปัญหาได้หากคนเลวเข้าถึงการถ่ายโอนข้อมูลหน่วยความจำได้ ปัญหานี้มีอยู่แม้ว่าจะไม่ได้ฝึกงาน (เนื่องจาก GC ไม่ใช่การกำหนดค่าเริ่มต้นด้วย ฯลฯ ) แต่มันก็ทำให้แย่ลงไปอีก เป็นความคิดที่ดีที่จะใช้char[]แทนStringข้อความที่ละเอียดอ่อนและทำให้เป็นศูนย์ทันทีที่ไม่จำเป็นต้องใช้อีกต่อไป
chris

71

มีคำถาม "การสัมภาษณ์ที่ติดหู" เช่นทำไมคุณถึงได้เท่ากับ! หากคุณรันโค้ดด้านล่าง

String s1 = "testString";
String s2 = "testString";
if(s1 == s2) System.out.println("equals!");

equals()หากคุณต้องการเปรียบเทียบสตริงคุณควรใช้ ข้อมูลด้านบนจะพิมพ์เท่ากับเพราะคอมไพเลอร์testStringได้รับการฝึกงานให้กับคุณแล้ว คุณสามารถฝึกงานสตริงด้วยตัวเองโดยใช้วิธีการฝึกงานตามที่แสดงในคำตอบก่อนหน้านี้ ....


5
ตัวอย่างของคุณมีความซับซ้อนทำให้เกิดการพิมพ์เดียวกันแม้ว่าคุณจะใช้equalsวิธีการนี้ คุณอาจต้องการเพิ่มการnew String()เปรียบเทียบเพื่อแสดงความแตกต่างให้ชัดเจนยิ่งขึ้น
giannis christofakis

@giannischristofakis แต่ถ้าเราใช้ String ใหม่ () จะไม่ == ล้มเหลว? java จะทำให้เป็นสตริงภายใน newed โดยอัตโนมัติเช่นกันหรือไม่?
Deepak Selvakumar

@giannischristofakis แน่นอนถ้าคุณใช้ String ใหม่ () มันจะล้มเหลวในวันที่ == แต่ String ใหม่ (... ). ฝึกงาน () จะไม่ล้มเหลวใน == เพราะฝึกงานจะส่งคืนสตริงเดียวกัน สมมติว่าคอมไพเลอร์กำลังทำ String ใหม่ () ฝึกงานเป็นตัวอักษร
maslan

42

JLS

JLS 7 3.10.5กำหนดและให้ตัวอย่างเชิงปฏิบัติ:

นอกจากนี้สตริงตัวอักษรมักจะหมายถึงอินสแตนซ์เดียวกันของคลาสสตริง นี่เป็นเพราะตัวอักษรสตริง - หรือโดยทั่วไปแล้วสตริงที่เป็นค่าของการแสดงออกอย่างต่อเนื่อง (§15.28) - เป็น "ฝึกงาน" เพื่อแบ่งปันกรณีที่ไม่ซ้ำกันโดยใช้วิธีการ String.intern

ตัวอย่าง 3.10.5-1 สตริงตัวอักษร

โปรแกรมประกอบด้วยชุดรวบรวม (§7.3):

package testPackage;
class Test {
    public static void main(String[] args) {
        String hello = "Hello", lo = "lo";
        System.out.print((hello == "Hello") + " ");
        System.out.print((Other.hello == hello) + " ");
        System.out.print((other.Other.hello == hello) + " ");
        System.out.print((hello == ("Hel"+"lo")) + " ");
        System.out.print((hello == ("Hel"+lo)) + " ");
        System.out.println(hello == ("Hel"+lo).intern());
    }
}
class Other { static String hello = "Hello"; }

และหน่วยรวบรวม:

package other;
public class Other { public static String hello = "Hello"; }

ผลิตผลลัพธ์:

true true true true false true

JVMs

JVMS 7 5.1 กล่าวว่าการฝึกงานจะดำเนินการอย่างน่าอัศจรรย์และมีประสิทธิภาพด้วยโครงสร้างเฉพาะCONSTANT_String_info(แตกต่างจากวัตถุอื่น ๆ ส่วนใหญ่ที่มีการแสดงออกทั่วไปมากขึ้น):

สตริงตัวอักษรเป็นการอ้างอิงถึงอินสแตนซ์ของคลาสสตริงและได้มาจากโครงสร้าง CONSTANT_String_info (§4.4.3) ในการเป็นตัวแทนไบนารีของคลาสหรืออินเตอร์เฟซ โครงสร้าง CONSTANT_String_info ให้ลำดับของจุดโค้ด Unicode ที่ประกอบเป็นตัวอักษรสตริง

ภาษาการเขียนโปรแกรม Java ต้องการตัวอักษรสตริงที่เหมือนกัน (นั่นคือตัวอักษรที่มีลำดับจุดรหัสเดียวกัน) ต้องอ้างถึงอินสแตนซ์เดียวกันของคลาส String (JLS §3.10.5) นอกจากนี้ถ้าเมธอด String.intern ถูกเรียกบนสตริงใด ๆ ผลลัพธ์จะเป็นการอ้างอิงไปยังอินสแตนซ์ของคลาสเดียวกันที่จะถูกส่งคืนหากสตริงนั้นปรากฏเป็นตัวอักษร ดังนั้นการแสดงออกต่อไปนี้จะต้องมีค่าจริง:

("a" + "b" + "c").intern() == "abc"

เพื่อรับสตริงตัวอักษร Java Virtual Machine จะตรวจสอบลำดับของจุดรหัสที่กำหนดโดยโครงสร้าง CONSTANT_String_info

  • หากก่อนหน้านี้มีการเรียกใช้เมธอด String.intern ในอินสแตนซ์ของคลาส String ที่มีลำดับของจุดโค้ด Unicode เหมือนกับที่กำหนดโดยโครงสร้าง

  • มิฉะนั้นอินสแตนซ์ใหม่ของคลาสสตริงจะถูกสร้างขึ้นซึ่งมีลำดับของจุดโค้ด Unicode ที่กำหนดโดยโครงสร้าง CONSTANT_String_info การอ้างอิงถึงอินสแตนซ์ของคลาสนั้นเป็นผลลัพธ์ของการสืบทอดสตริงตามตัวอักษร ในที่สุดวิธีการฝึกงานของอินสแตนซ์สตริงใหม่จะถูกเรียกใช้

bytecode

ลองแยกรหัส OpenJDK 7 บางส่วนเพื่อดูการทำงานจริง

ถ้าเราแปลความหมาย:

public class StringPool {
    public static void main(String[] args) {
        String a = "abc";
        String b = "abc";
        String c = new String("abc");
        System.out.println(a);
        System.out.println(b);
        System.out.println(a == c);
    }
}

เรามีสระว่ายน้ำคงที่:

#2 = String             #32   // abc
[...]
#32 = Utf8               abc

และmain:

 0: ldc           #2          // String abc
 2: astore_1
 3: ldc           #2          // String abc
 5: astore_2
 6: new           #3          // class java/lang/String
 9: dup
10: ldc           #2          // String abc
12: invokespecial #4          // Method java/lang/String."<init>":(Ljava/lang/String;)V
15: astore_3
16: getstatic     #5          // Field java/lang/System.out:Ljava/io/PrintStream;
19: aload_1
20: invokevirtual #6          // Method java/io/PrintStream.println:(Ljava/lang/String;)V
23: getstatic     #5          // Field java/lang/System.out:Ljava/io/PrintStream;
26: aload_2
27: invokevirtual #6          // Method java/io/PrintStream.println:(Ljava/lang/String;)V
30: getstatic     #5          // Field java/lang/System.out:Ljava/io/PrintStream;
33: aload_1
34: aload_3
35: if_acmpne     42
38: iconst_1
39: goto          43
42: iconst_0
43: invokevirtual #7          // Method java/io/PrintStream.println:(Z)V

สังเกตว่า:

  • 0และ3: ldc #2โหลดค่าคงที่เดียวกัน(ตัวอักษร)
  • 12: อินสแตนซ์ของสตริงใหม่ถูกสร้างขึ้น (โดยมี#2อาร์กิวเมนต์เป็น)
  • 35: aและcถูกเปรียบเทียบเป็นวัตถุปกติด้วยif_acmpne

การเป็นตัวแทนของสตริงคงที่นั้นค่อนข้างน่าอัศจรรย์ใน bytecode:

  • มันมีโครงสร้างCONSTANT_String_infoเฉพาะซึ่งแตกต่างจากวัตถุปกติ (เช่นnew String )
  • struct ชี้ไปที่โครงสร้าง CONSTANT_Utf8_infoที่มีข้อมูล นั่นเป็นข้อมูลที่จำเป็นเพียงอย่างเดียวในการแสดงสตริง

และการอ้างอิง JVMS ข้างต้นดูเหมือนจะบอกว่าเมื่อใดก็ตามที่ Utf8 ชี้ไปที่เหมือนกันจากนั้นอินสแตนซ์ที่เหมือนกันจะถูกโหลดโดย ldcชี้ไปที่จะเหมือนกันกรณีแล้วเหมือนจะถูกโหลดโดย

ฉันได้ทำการทดสอบที่คล้ายกันสำหรับสาขาและ:

  • static final String s = "abc"ชี้ไปที่ตารางค่าคงที่ผ่านแอตทริบิวต์ค่าคงที่
  • เขตข้อมูลที่ไม่ใช่ครั้งสุดท้ายไม่มีแอตทริบิวต์นั้น แต่ยังสามารถเริ่มต้นได้ด้วย ldc

สรุป : มีการสนับสนุน bytecode โดยตรงสำหรับสตริงพูลและการแสดงหน่วยความจำนั้นมีประสิทธิภาพ

โบนัส: เปรียบเทียบกับพูลจำนวนเต็มซึ่งไม่มีการสนับสนุนไบต์โดยตรง (เช่นไม่มีCONSTANT_String_infoอะนาล็อก)


19

อัพเดตสำหรับ Java 8 หรือบวกหรือบวก ใน Java 8 พื้นที่ PermGen (การสร้างถาวร) จะถูกลบและแทนที่ด้วย Meta Space หน่วยความจำพูล String ถูกย้ายไปที่ฮีปของ JVM

เมื่อเปรียบเทียบกับ Java 7 ขนาดของ String Pool จะเพิ่มขึ้นในฮีป ดังนั้นคุณมีพื้นที่เพิ่มเติมสำหรับการวางสายภายใน แต่คุณมีหน่วยความจำน้อยกว่าสำหรับแอปพลิเคชันทั้งหมด

อีกสิ่งหนึ่งที่คุณรู้อยู่แล้วว่าเมื่อเปรียบเทียบวัตถุ 2 (การอ้างอิงของ) ใน Java, ' ==' ใช้สำหรับการเปรียบเทียบการอ้างอิงของวัตถุ ' equals' จะใช้สำหรับการเปรียบเทียบเนื้อหาของวัตถุ

ลองตรวจสอบรหัสนี้:

String value1 = "70";
String value2 = "70";
String value3 = new Integer(70).toString();

ผลลัพธ์:

value1 == value2 ---> จริง

value1 == value3 ---> เท็จ

value1.equals(value3) ---> จริง

value1 == value3.intern() ---> จริง

นั่นเป็นเหตุผลที่คุณควรใช้ ' equals' เพื่อเปรียบเทียบ 2 วัตถุสตริง และนั่นคือวิธีที่intern()มีประโยชน์


2

String interning เป็นเทคนิคการปรับให้เหมาะสมโดยคอมไพเลอร์ หากคุณมีตัวอักษรสตริงที่เหมือนกันสองตัวในหนึ่งหน่วยการรวบรวมแล้วโค้ดที่สร้างขึ้นจะตรวจสอบให้แน่ใจว่ามีวัตถุสตริงเพียงอันเดียวที่สร้างขึ้นสำหรับอินสแตนซ์ทั้งหมดของตัวอักษรนั้น (อักขระที่อยู่ในเครื่องหมายคำพูดคู่) ภายในชุดประกอบ

ฉันมาจากพื้นหลัง C # ดังนั้นฉันสามารถอธิบายได้โดยให้ตัวอย่างจากที่:

object obj = "Int32";
string str1 = "Int32";
string str2 = typeof(int).Name;

ผลลัพธ์ของการเปรียบเทียบดังต่อไปนี้:

Console.WriteLine(obj == str1); // true
Console.WriteLine(str1 == str2); // true    
Console.WriteLine(obj == str2); // false !?

Note1 : วัตถุถูกเปรียบเทียบโดยการอ้างอิง

Note2 : typeof (int) .Name ประเมินโดยวิธีการไตร่ตรองดังนั้นจึงไม่ได้รับการประเมิน ณ เวลารวบรวม ที่นี่การเปรียบเทียบเหล่านี้ทำในเวลารวบรวม

การวิเคราะห์ผลลัพธ์: 1) จริงเพราะทั้งคู่มีตัวอักษรเหมือนกันดังนั้นรหัสที่สร้างขึ้นจะมีเพียงวัตถุเดียวที่อ้างอิง "Int32" ดูหมายเหตุ 11

2) ถูกต้องเนื่องจากเนื้อหาของทั้งสองค่าถูกตรวจสอบว่าเหมือนกัน

3) FALSE เพราะ str2 และ obj ไม่มีตัวอักษรเหมือนกัน ดูหมายเหตุ 2


3
มันแข็งแกร่งกว่านั้น สตริงตัวอักษรใด ๆ ที่โหลดโดย classloader เดียวกันจะอ้างถึงสตริงเดียวกัน ดูข้อกำหนด JLS และ JVM
มาร์ควิสแห่ง Lorne

1
@ user207421 ที่จริงแล้วมันไม่เกี่ยวข้องแม้แต่กับ classloader ที่สตริงตัวอักษรเป็นของ
Holger

1
Java interning() method basically makes sure that if String object is present in SCP, If yes then it returns that object and if not then creates that objects in SCP and return its references

for eg: String s1=new String("abc");
        String s2="abc";
        String s3="abc";

s1==s2// false, because 1 object of s1 is stored in heap and other in scp(but this objects doesn't have explicit reference) and s2 in scp
s2==s3// true

now if we do intern on s1
s1=s1.intern() 

//JVM checks if there is any string in the pool with value “abc” is present? Since there is a string object in the pool with value “abc”, its reference is returned.
Notice that we are calling s1 = s1.intern(), so the s1 is now referring to the string pool object having value abc”.
At this point, all the three string objects are referring to the same object in the string pool. Hence s1==s2 is returning true now.

0

จากหนังสือ OCP Java SE 11 โปรแกรมเมอร์ Deshmukh ฉันพบคำอธิบายที่ง่ายที่สุดสำหรับการ Interning ซึ่งเป็นดังนี้: เนื่องจากสตริงเป็นวัตถุและเนื่องจากวัตถุทั้งหมดใน Java จะถูกเก็บไว้ในพื้นที่ฮีปเสมอเท่านั้นสตริงทั้งหมดจะถูกเก็บไว้ในพื้นที่ฮีพ อย่างไรก็ตาม Java เก็บสตริงที่สร้างขึ้นโดยไม่ใช้คำหลักใหม่ในพื้นที่พิเศษของพื้นที่ฮีพซึ่งเรียกว่า "สตริงพูล" Java เก็บสตริงที่สร้างขึ้นโดยใช้คำหลักใหม่ในพื้นที่ฮีปปกติ

วัตถุประสงค์ของสตริงพูลคือเพื่อรักษาชุดของสตริงที่ไม่ซ้ำกัน เมื่อใดก็ตามที่คุณสร้างสตริงใหม่โดยไม่ใช้คำหลักใหม่ Java จะตรวจสอบว่ามีสตริงเดียวกันอยู่แล้วในกลุ่มสตริง หากเป็นเช่นนั้น Java จะส่งคืนการอ้างอิงไปยังวัตถุ String เดียวกันและหากไม่เป็นเช่นนั้น Java จะสร้างวัตถุ String ใหม่ในพูลสตริงและส่งคืนการอ้างอิง ตัวอย่างเช่นหากคุณใช้สตริง "hello" สองครั้งในรหัสของคุณดังแสดงด้านล่างคุณจะได้รับการอ้างอิงถึงสตริงเดียวกัน เราสามารถทดสอบทฤษฎีนี้โดยการเปรียบเทียบตัวแปรอ้างอิงที่แตกต่างกันสองตัวโดยใช้ตัวดำเนินการ==ดังที่แสดงในรหัสต่อไปนี้:

String str1 = "hello";
String str2 = "hello";
System.out.println(str1 == str2); //prints true

String str3 = new String("hello");
String str4 = new String("hello");

System.out.println(str1 == str3); //prints false
System.out.println(str3 == str4); //prints false 

==โอเปอเรเตอร์จะตรวจสอบว่าการอ้างอิงสองรายการชี้ไปที่วัตถุเดียวกันหรือไม่และส่งกลับค่าจริงถ้ามีการอ้างอิง ในโค้ดด้านบนstr2ได้รับการอ้างอิงถึงวัตถุ String เดียวกันซึ่งสร้างขึ้นก่อนหน้านี้ อย่างไรก็ตามstr3และstr4ได้รับการอ้างอิงถึงสองวัตถุ String ที่แตกต่างกันอย่างสิ้นเชิง นั่นคือเหตุผลที่str1 == str2ส่งกลับค่าจริง แต่str1 == str3และstr3 == str4กลับเท็จ อันที่จริงแล้วเมื่อคุณสร้าง String ใหม่ ("hello"); วัตถุ String สองตัวถูกสร้างขึ้นแทนที่จะเป็นเพียงครั้งเดียวถ้านี่เป็นครั้งแรกที่สตริง "hello" ถูกใช้ในที่ใดก็ได้ในโปรแกรม - หนึ่งในกลุ่มสตริงเนื่องจากการใช้สตริงที่ยกมาและหนึ่งในพื้นที่ฮีปปกติเพราะ ของการใช้คำหลักใหม่

String pooling เป็นวิธีการบันทึกหน่วยความจำของโปรแกรมของ Java โดยหลีกเลี่ยงการสร้างวัตถุ String หลายรายการที่มีค่าเดียวกัน เป็นไปได้ที่จะได้รับสตริงจากกลุ่มสตริงสำหรับสตริงที่สร้างขึ้นโดยใช้คำหลักใหม่โดยใช้วิธีการฝึกงานของ String มันถูกเรียกว่า "ฝึกงาน" ของวัตถุสตริง ตัวอย่างเช่น,

String str1 = "hello";
String str2 = new String("hello");
String str3 = str2.intern(); //get an interned string obj

System.out.println(str1 == str2); //prints false
System.out.println(str1 == str3); //prints true
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.