เมื่อใดที่เราควรใช้วิธีการฝึกงานของตัวอักษร String on String


187

ตามString # ฝึกงาน () , internวิธีการที่ควรจะกลับ String จากสระว่ายน้ำ String ถ้าเชือกที่พบในสระว่ายน้ำ String มิฉะนั้นวัตถุสตริงใหม่จะถูกเพิ่มเข้ามาในสระว่ายน้ำ String และการอ้างอิงของสายนี้จะถูกส่งกลับ

ดังนั้นฉันลองทำสิ่งนี้:

String s1 = "Rakesh";
String s2 = "Rakesh";
String s3 = "Rakesh".intern();

if ( s1 == s2 ){
    System.out.println("s1 and s2 are same");  // 1.
}

if ( s1 == s3 ){
    System.out.println("s1 and s3 are same" );  // 2.
}

ฉันคาดหวังว่าs1 and s3 are sameจะถูกพิมพ์เมื่อ s3 ถูก interned และs1 and s2 are sameจะไม่ถูกพิมพ์ แต่ผลลัพธ์คือ: ทั้งสองบรรทัดถูกพิมพ์ ดังนั้นนั่นหมายความว่าค่าคงที่สตริงเริ่มต้นจะถูกฝึกงาน แต่ถ้าเป็นเช่นนั้นแล้วทำไมเราถึงต้องการinternวิธีการ? กล่าวอีกนัยหนึ่งเราควรใช้วิธีนี้เมื่อใด?


14
Javadoc ที่คุณเชื่อมโยงระบุด้วย "สตริงตัวอักษรและนิพจน์ค่าคงที่สตริงทั้งหมดจะถูก interned"
Jorn


1
ไม่ซ้ำกันแน่นอน ..
Bozho

1
@ จอน: ถูกต้อง แล้วทำไมเราถึงมีinternวิธีเป็นสาธารณะ เราไม่ควรมีinternวิธีการส่วนตัวเพื่อให้ไม่มีใครสามารถเข้าถึงได้ หรือมีจุดประสงค์ของวิธีนี้หรือไม่?
Rakesh Juyal

2
@RakeshJuyal: วิธีการฝึกงานถูกกำหนดไว้ในประเภทสตริงซึ่งสามารถเป็นตัวอักษรสตริงหรือตัวแปร คุณจะฝึกงานตัวแปรอย่างไรถ้าวิธีนั้นเป็นแบบส่วนตัว?
bobbyalex

คำตอบ:


230

Java ฝึกงานตัวอักษรสตริงโดยอัตโนมัติ ซึ่งหมายความว่าในหลายกรณีตัวดำเนินการ == จะทำงานเพื่อ Strings ในลักษณะเดียวกับที่ทำกับ ints หรือค่าดั้งเดิมอื่น ๆ

เนื่องจากการฝึกงานเป็นไปโดยอัตโนมัติสำหรับตัวอักษรสตริงintern()จึงต้องใช้วิธีนี้กับสตริงที่สร้างขึ้นด้วยnew String()

ใช้ตัวอย่างของคุณ:

String s1 = "Rakesh";
String s2 = "Rakesh";
String s3 = "Rakesh".intern();
String s4 = new String("Rakesh");
String s5 = new String("Rakesh").intern();

if ( s1 == s2 ){
    System.out.println("s1 and s2 are same");  // 1.
}

if ( s1 == s3 ){
    System.out.println("s1 and s3 are same" );  // 2.
}

if ( s1 == s4 ){
    System.out.println("s1 and s4 are same" );  // 3.
}

if ( s1 == s5 ){
    System.out.println("s1 and s5 are same" );  // 4.
}

จะกลับมา:

s1 and s2 are same
s1 and s3 are same
s1 and s5 are same

ในทุกกรณีนอกเหนือจากของs4ตัวแปรค่าที่ถูกสร้างขึ้นอย่างชัดเจนโดยใช้newผู้ประกอบการและสถานที่ที่internวิธีการที่ไม่ได้ถูกนำมาใช้เป็นของผลก็เป็นเช่นเดียวไม่เปลี่ยนรูปที่ถูกส่งกลับมาว่ายน้ำคงที่สตริง JVM ของ

อ้างถึงJavaTechniques "ความเท่าเทียมกันของสตริงและการฝึกงาน"สำหรับข้อมูลเพิ่มเติม


ฉันสมมติว่า Java ฝึกงานตัวอักษร String โดยอัตโนมัติเพื่อวัตถุประสงค์ในการเพิ่มประสิทธิภาพ มันสามารถทำได้อย่างปลอดภัยเพียงเพราะสตริงไม่เปลี่ยนรูปถูกต้องหรือไม่
สไตล์

ใหม่สำหรับ Java (ฉันมาจากโลก C # .NET) และบางครั้งฉันเห็นในโครงการ Java ดั้งเดิม "" .Intern () ดังนั้นหากฉันเข้าใจอย่างถูกต้องว่านี่เป็น "ไร้สาระ" สำหรับสตริงว่าง
hfrmobile

4
@Mueluel คำอธิบายที่ดีคำถามของฉันคือสิ่งที่อาจสร้างวัตถุที่นี่ในตัวอย่างของคุณ นี่คือฉันอัสสัมชั: String s1 = "Rakesh"; แรก OB1 String s4 = new String("Rakesh");ส่วนที่เหลือสอง OB2 ดังนั้น (S2, S3, S5) อ้างอิงวัตถุเดียวกัน (OB1) สร้างขึ้นใน 'สตริงสระว่ายน้ำ' ดังนั้นฉันสามารถพูดได้ว่า.intern()วิธีการที่ใช้ในการป้องกันการสร้างวัตถุใหม่หากสายเดียวกันที่มีอยู่ในstring poolถ้า การสันนิษฐานของฉันผิด
HybrisHelp

1
ลิงก์ JavaTechniques เสีย
SJuan76


20

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

ข้อได้เปรียบเล็ก ๆ น้อย ๆ อีกอย่างหนึ่งของการใช้งาน Strings คือ==สามารถใช้ (สำเร็จ!) เพื่อเปรียบเทียบ Strings หากการรับประกันสตริงที่เกี่ยวข้องทั้งหมดถูกฝึกงาน นอกเหนือจากไวยากรณ์ลีนแล้วนี่ยังเป็นการปรับปรุงประสิทธิภาพ แต่อย่างที่คนอื่น ๆ ได้ชี้ให้เห็นการทำเช่นนี้มีความเสี่ยงอย่างมากในการแนะนำข้อผิดพลาดในการเขียนโปรแกรมดังนั้นสิ่งนี้ควรทำเฉพาะในฐานะที่เป็นมาตรการสุดท้ายเท่านั้น

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


@ The downside is that interning a String takes more time than simply throwing it on the heap, and that the space for interned Strings may be limitedแม้ว่าคุณจะไม่ได้ใช้วิธีการฝึกงานสำหรับค่าคงที่สตริงมันจะถูกฝึกงานโดยอัตโนมัติ
Rakesh Juyal

2
@ ราเคช: มีไม่มากที่ค่าคงที่สตริงในคลาสที่กำหนดใด ๆ ดังนั้นจึงไม่เป็นปัญหาของพื้นที่ / เวลากับค่าคงที่
David Rodríguez - dribeas

ใช่ความคิดเห็นของ Rakesh ไม่ได้ใช้เพราะการฝึกงาน Strings นั้นทำเฉพาะกับ Strings ที่ "สร้าง" อย่างใดไม่ว่าจะโดยการจัดการภายในหรือโดยการดึงจากฐานข้อมูลหรือ ค่าคงที่เราไม่มีทางเลือก
คาร์ล Smotricz

2
+1 ฉันคิดว่านี่เป็นตัวอย่างที่ดีของการฝึกงานที่เหมาะสม ฉันไม่เห็นด้วยกับ==เงื่อนไขแม้ว่า
Alexander Pogrebnyak

1
จาก Java 7 เป็นต้นไป "Pool String" ถูกนำไปใช้ในพื้นที่ของ heap ดังนั้นจึงได้รับข้อดีทั้งหมดของการจัดเก็บฝึกงานการเก็บขยะและขนาดของมันไม่ จำกัด ก็สามารถเพิ่มได้มากถึงขนาดฮีป หน่วยความจำสำหรับสตริง)
Anil Uttani

15

ฉันต้องการเพิ่ม 2 เซ็นต์ของฉันในการใช้==กับสตริง interned

สิ่งแรกที่ทำก็คือString.equalsthis==object

ดังนั้นแม้ว่าจะมีประสิทธิภาพที่ลดลงเล็กน้อย (คุณไม่ได้เรียกใช้เมธอด) จากมุมมองของผู้ดูแลที่ใช้==นั้นเป็นฝันร้ายเพราะสตริงการฝึกงานบางตัวมีแนวโน้มที่จะไม่ได้รับการฝึกงาน

ดังนั้นฉันจึงไม่แนะนำให้ใช้กรณีพิเศษของ==สตริง interned แต่ควรใช้equalsเป็นลูกห่านที่ตั้งใจไว้เสมอ

แก้ไข: ฝึกงานกลายเป็นไม่ฝึกงาน:

V1.0
public class MyClass
{
  private String reference_val;

  ...

  private boolean hasReferenceVal ( final String[] strings )
  {
    for ( String s : strings )
    {
      if ( s == reference_val )
      {
        return true;
      }
    }

    return false;
  }

  private void makeCall ( )
  {
     final String[] interned_strings =  { ... init with interned values ... };

     if ( hasReference( interned_strings ) )
     {
        ...
     }
  }
}

ในผู้ดูแลเวอร์ชัน 2.0 ตัดสินใจhasReferenceValเผยแพร่โดยไม่ต้องลงรายละเอียดมากนักซึ่งคาดว่าจะมีสตริงของการฝึกงาน

V2.0
public class MyClass
{
  private String reference_val;

  ...

  public boolean hasReferenceVal ( final String[] strings )
  {
    for ( String s : strings )
    {
      if ( s == reference_val )
      {
        return true;
      }
    }

    return false;
  }

  private void makeCall ( )
  {
     final String[] interned_strings =  { ... init with interned values ... };

     if ( hasReference( interned_strings ) )
     {
        ...
     }
  }
}

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


"สตริงการฝึกงานบางรายการมีแนวโน้มที่จะไม่ได้รับการฝึกงาน" ว้าวนั่นคงจะแปลก ... คุณสามารถอ้างอิงการอ้างอิงได้ไหม
คาร์ล Smotricz

2
ตกลงฉันคิดว่าคุณกำลังอ้างถึง Strings เดินออกจากสระว่ายน้ำฝึกงานและเข้าสู่กองด้วยเวทมนตร์ใน JVM สิ่งที่คุณพูดคือ == ทำให้คลาสของข้อผิดพลาดของโปรแกรมเมอร์มีโอกาสมากขึ้น
คาร์ล Smotricz

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

1
ฝึกงานไม่ดีสำหรับการเปรียบเทียบโดยตรง (==) แม้ว่ามันจะทำงานได้ดีถ้าทั้งสองสตริงมีการฝึกงาน มันยอดเยี่ยมในการลดหน่วยความจำทั้งหมดที่ใช้: เมื่อใช้สตริงเดียวกันมากกว่า 1 แห่ง
tgkprog

12

สตริงตัวอักษรและค่าคงที่จะถูกฝึกงานโดยค่าเริ่มต้น นั่นคือ"foo" == "foo"(ประกาศโดยตัวอักษร String) new String("foo") != new String("foo")แต่


4
ดังนั้นคำถามคือเมื่อเราควรใช้ intern ,
Rakesh Juyal

ที่ชี้ไปที่stackoverflow.com/questions/1833581/when-to-use-internและคำถามอื่น ๆ อีกจำนวนหนึ่งคำถามบางข้อจากเมื่อวานนี้
Bozho

แจ้งให้เราทราบหากความเข้าใจของฉันสำหรับคำสั่งนี้: String literals and constants are interned by defaultถูกต้อง new String("foo")-> ที่นี่หนึ่งสตริง "foo" ตามตัวอักษรถูกสร้างขึ้นใน String pool และอีกหนึ่งรายการในฮีปดังนั้นจึงมีการสร้างวัตถุทั้งหมด 2 รายการ
dkb

8

เรียนรู้ Java String Intern - หนึ่งเดียวสำหรับทุกคน

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

กฎด้านล่างจะช่วยให้คุณเข้าใจแนวคิดในแง่ที่ชัดเจน:

  1. คลาส String รักษาสระว่ายน้ำฝึกงานซึ่งว่างเปล่าในตอนแรก กลุ่มนี้จะต้องรับประกันว่าจะมีวัตถุสตริงที่มีค่าเฉพาะเท่านั้น
  2. ตัวอักษรสตริงทั้งหมดที่มีค่าเดียวกันจะต้องถือว่าเป็นวัตถุหน่วยความจำตำแหน่งเดียวกันเพราะไม่มีความแตกต่าง ดังนั้นตัวอักษรดังกล่าวทั้งหมดที่มีค่าเท่ากันจะสร้างรายการเดี่ยวในพูลภายในและจะอ้างถึงตำแหน่งหน่วยความจำเดียวกัน
  3. การต่อตัวอักษรสองตัวหรือมากกว่าเข้าด้วยกันก็เป็นตัวอักษรเช่นกัน (ดังนั้นกฎข้อที่ 2 จะใช้งานได้สำหรับพวกเขา)
  4. แต่ละสตริงที่สร้างเป็นวัตถุ (เช่นโดยวิธีอื่นใดยกเว้นตามตัวอักษร) จะมีตำแหน่งหน่วยความจำที่แตกต่างกันและจะไม่ทำรายการใด ๆ ในพูลภายใน
  5. การต่อตัวอักษรที่ไม่ใช่ตัวอักษรเข้าด้วยกันจะทำให้ไม่ใช่ตัวอักษร ดังนั้นวัตถุผลลัพธ์จะมีที่ตั้งหน่วยความจำใหม่และจะไม่ทำรายการในสระว่ายน้ำฝึกงาน
  6. การเรียกใช้วิธีการฝึกงานบนวัตถุสตริงสร้างวัตถุใหม่ที่เข้าสู่การพูลหรือส่งคืนวัตถุที่มีอยู่จากพูลที่มีค่าเท่ากัน การเรียกใช้บนวัตถุใด ๆ ที่ไม่ได้อยู่ในพูลภายในไม่ย้ายวัตถุไปยังพูล มันค่อนข้างสร้างวัตถุอื่นที่เข้าสู่กลุ่ม

ตัวอย่าง:

String s1=new String (“abc”);
String s2=new String (“abc”);
If (s1==s2)  //would return false  by rule #4
If (“abc == a”+”bc )  //would return true by rules #2 and #3
If (“abc == s1 )  //would return false  by rules #1,2 and #4
If (“abc == s1.intern() )  //would return true  by rules #1,2,4 and #6
If ( s1 == s2.intern() )      //wound return false by rules #1,4, and #6

หมายเหตุ: กรณีที่สร้างแรงบันดาลใจสำหรับฝึกงานสตริงไม่ได้กล่าวถึงที่นี่ อย่างไรก็ตามการบันทึกหน่วยความจำจะเป็นหนึ่งในวัตถุประสงค์หลักอย่างแน่นอน


ขอขอบคุณสำหรับ # 3 ผมไม่ทราบ :)
kaay

4

คุณควรทำสองช่วงเวลาซึ่งเป็นเวลารวบรวมและเวลารันไทม์ตัวอย่างเช่น:

//example 1 
"test" == "test" // --> true 
"test" == "te" + "st" // --> true

//example 2 
"test" == "!test".substring(1) // --> false
"test" == "!test".substring(1).intern() // --> true

ในมือข้างหนึ่งในตัวอย่างที่ 1 เราพบว่าผลลัพธ์ทั้งหมดกลับเป็นจริงเพราะในเวลารวบรวม jvm จะใส่ "test" ลงในพูลของสตริงตามตัวอักษรถ้า jvm ค้นหา "test" ที่มีอยู่แล้ว มันจะใช้หนึ่งที่มีอยู่ในตัวอย่างที่ 1 สตริง "ทดสอบ" ทั้งหมดชี้ไปยังที่อยู่หน่วยความจำเดียวกันดังนั้นตัวอย่างที่ 1 จะกลับมาจริง ในอีกตัวอย่าง 2 วิธีของ substring () ดำเนินการในเวลารันไทม์ในกรณีของ "test" == "! test" .substring (1), พูลจะสร้างวัตถุสตริงสองอัน " ทดสอบ "และ"! test "ดังนั้นจึงเป็นวัตถุอ้างอิงที่แตกต่างกันดังนั้นกรณีนี้จะส่งคืนค่าเท็จในกรณีของ" test "=="! test ".substring (1) .Intern () วิธีการฝึกงาน ( ) จะใส่ ""! test ".substring (1)" ลงในพูลของสตริงตัวอักษร


3

http://en.wikipedia.org/wiki/String_interning

string interning เป็นวิธีการเก็บสำเนาของค่าสตริงที่แตกต่างกันเพียงหนึ่งสำเนาเท่านั้นซึ่งจะต้องไม่เปลี่ยนรูป สตริงการฝึกงานทำให้งานการประมวลผลสตริงบางอย่างมีเวลามากขึ้นหรือใช้พื้นที่อย่างมีประสิทธิภาพโดยต้องใช้เวลามากขึ้นเมื่อสร้างหรือฝึกงานสตริง ค่าที่แตกต่างจะถูกเก็บไว้ในพูลฝึกงานสตริง


2

Interned Strings หลีกเลี่ยง Strings ที่ซ้ำกัน Interning ช่วยประหยัด RAM โดยเสียเวลาของ CPU ในการตรวจจับและแทนที่ Strings ที่ซ้ำกัน มีเพียงหนึ่งสำเนาของแต่ละสตริงที่ได้รับการฝึกงานไม่ว่าจะมีการอ้างอิงจำนวนเท่าใดชี้ไปที่มัน เนื่องจาก Strings นั้นไม่เปลี่ยนรูปถ้าสองวิธีที่ต่างกันใช้สตริงเดียวกันโดยบังเอิญพวกเขาสามารถแชร์สำเนาของ String เดียวกันได้ กระบวนการแปลงสตริงที่ซ้ำกันเป็นสตริงที่ใช้ร่วมกันนั้นเรียกว่าinterning.String.intern ()จะให้ที่อยู่ของสตริงต้นแบบมาตรฐานซึ่งเป็นที่ยอมรับ คุณสามารถเปรียบเทียบสตริงที่อยู่ภายในด้วย == อย่างง่าย (ซึ่งเปรียบเทียบพอยน์เตอร์) แทนเท่ากับซึ่งเปรียบเทียบอักขระของสตริงหนึ่งต่อหนึ่ง เนื่องจากสตริงไม่สามารถเปลี่ยนแปลงได้กระบวนการฝึกงานมีอิสระที่จะประหยัดพื้นที่เพิ่มเติมโดยไม่สร้างสตริงตัวอักษรแยกต่างหากสำหรับ "หม้อ" เมื่อมีอยู่เป็นสตริงย่อยของตัวอักษรอื่นเช่น "hippopotamus"

หากต้องการดูhttp://mindprod.com/jgloss/interned.htmlเพิ่มเติม


2
String s1 = "Anish";
        String s2 = "Anish";

        String s3 = new String("Anish");

        /*
         * When the intern method is invoked, if the pool already contains a
         * string equal to this String object as determined by the
         * method, then the string from the pool is
         * returned. Otherwise, this String object is added to the
         * pool and a reference to this String object is returned.
         */
        String s4 = new String("Anish").intern();
        if (s1 == s2) {
            System.out.println("s1 and s2 are same");
        }

        if (s1 == s3) {
            System.out.println("s1 and s3 are same");
        }

        if (s1 == s4) {
            System.out.println("s1 and s4 are same");
        }

เอาท์พุท

s1 and s2 are same
s1 and s4 are same

2
String p1 = "example";
String p2 = "example";
String p3 = "example".intern();
String p4 = p2.intern();
String p5 = new String(p3);
String p6 = new String("example");
String p7 = p6.intern();

if (p1 == p2)
    System.out.println("p1 and p2 are the same");
if (p1 == p3)
    System.out.println("p1 and p3 are the same");
if (p1 == p4)
    System.out.println("p1 and p4 are the same");
if (p1 == p5)
    System.out.println("p1 and p5 are the same");
if (p1 == p6)
    System.out.println("p1 and p6 are the same");
if (p1 == p6.intern())
    System.out.println("p1 and p6 are the same when intern is used");
if (p1 == p7)
    System.out.println("p1 and p7 are the same");

เมื่อสองสายถูกสร้างขึ้นอย่างอิสระintern()ช่วยให้คุณสามารถเปรียบเทียบพวกเขาและยังช่วยคุณในการสร้างการอ้างอิงในกลุ่มสระว่ายน้ำถ้าการอ้างอิงไม่ได้อยู่ก่อน

เมื่อคุณใช้String s = new String(hi)จาวาจะสร้างอินสแตนซ์ใหม่ของสตริง แต่เมื่อคุณใช้String s = "hi"จาวาจะตรวจสอบว่ามีอินสแตนซ์ของคำว่า "hi" ในรหัสหรือไม่และถ้ามีอยู่มันจะส่งคืนการอ้างอิง

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

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

แต่ในกรณีของ p5 เมื่อคุณใช้:

String p5 = new String(p3);

คัดลอกเนื้อหาของ p3 เท่านั้นและ p5 ถูกสร้างขึ้นใหม่ ดังนั้นจึงไม่ได้ฝึกงาน

ดังนั้นผลลัพธ์จะเป็น:

p1 and p2 are the same
p1 and p3 are the same
p1 and p4 are the same
p1 and p6 are the same when intern is used
p1 and p7 are the same

2
    public static void main(String[] args) {
    // TODO Auto-generated method stub
    String s1 = "test";
    String s2 = new String("test");
    System.out.println(s1==s2);              //false
    System.out.println(s1==s2.intern());    //true --> because this time compiler is checking from string constant pool.
}

1

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

ที่มา: ฝึกงานสตริงใน java คืออะไร?


1

ดังที่คุณกล่าวไว้intern()วิธีการสตริงนั้นจะค้นพบจาก Pool String ก่อนหากพบจากนั้นจะส่งคืนวัตถุที่ชี้ไปที่นั้นหรือจะเพิ่ม String ใหม่ลงในพูล

    String s1 = "Hello";
    String s2 = "Hello";
    String s3 = "Hello".intern();
    String s4 = new String("Hello");

    System.out.println(s1 == s2);//true
    System.out.println(s1 == s3);//true
    System.out.println(s1 == s4.intern());//true

s1และs2มีวัตถุทั้งสองชี้ไปที่สระว่ายน้ำสตริง "สวัสดี" และใช้"Hello".intern()จะพบว่าและs1 s2ดังนั้นผลตอบแทนที่แท้จริงเช่นเดียวกับ"s1 == s3"s3.intern()


สิ่งนี้ไม่ได้ให้ข้อมูลใหม่มากนัก มีคำตอบที่ยกเว้นแล้ว
Alexander

0

โดยใช้การอ้างอิงวัตถุฮีปถ้าเราต้องการให้สอดคล้องกัน การอ้างอิงวัตถุสตริงคงที่ที่แล้วเราควรไปฝึกงาน ()

String s1 = new String("Rakesh");
String s2 = s1.intern();
String s3 = "Rakesh";

System.out.println(s1 == s2); // false
System.out.println(s2 == s3); // true

มุมมองภาพ ป้อนคำอธิบายรูปภาพที่นี่

ขั้นตอนที่ 1: วัตถุที่มีข้อมูล 'Rakesh' ถูกสร้างขึ้นในกองและสระว่ายน้ำคงที่สตริง s1 ยังชี้ไปที่วัตถุฮีปเสมอ

ขั้นตอนที่ 2: โดยการใช้การอ้างอิงวัตถุฮีป s1 เรากำลังพยายามรับสตริงการอ้างอิงวัตถุพูลที่สอดคล้องกัน s2 โดยใช้ฝึกงาน ()

ขั้นตอนที่ 3: สร้างวัตถุที่มีข้อมูล 'Rakesh' โดยตั้งใจในกลุ่มค่าคงที่สตริงอ้างอิงโดยชื่อ s3

ในฐานะผู้ประกอบการ "==" มีความหมายสำหรับการเปรียบเทียบการอ้างอิง

รับเท็จสำหรับ s1 == s2

รับจริงสำหรับ s2 == s3

หวังว่าความช่วยเหลือนี้ !!

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