จะเกิดอะไรขึ้นอย่างแท้จริงหาก java.lang.String ไม่เป็นที่สิ้นสุด


16

ฉันเป็นนักพัฒนา Java มานานและในที่สุดหลังจากวิชาเอกฉันมีเวลาศึกษาอย่างเหมาะสมเพื่อทำการสอบรับรอง ... สิ่งหนึ่งที่ทำให้ฉันรำคาญอยู่เสมอคือ String เป็น "ขั้นสุดท้าย" ฉันเข้าใจเมื่ออ่านเกี่ยวกับปัญหาด้านความปลอดภัยและสิ่งที่เกี่ยวข้อง ... แต่จริงๆแล้วทุกคนมีตัวอย่างที่แท้จริงของเรื่องนี้หรือไม่?

ตัวอย่างเช่นจะเกิดอะไรขึ้นหาก String ไม่เป็นที่สิ้นสุด มันไม่ได้อยู่ในรูบี ฉันไม่เคยได้ยินเรื่องร้องเรียนใด ๆ ที่มาจากชุมชน Ruby ... และฉันรู้ว่า StringUtils และคลาสที่เกี่ยวข้องที่คุณต้องใช้เองหรือค้นหาผ่านเว็บเพื่อใช้พฤติกรรมนั้น (โค้ด 4 บรรทัด) คุณ ยินดีที่จะ


9
คุณอาจสนใจคำถามนี้ใน Stack Overflow: stackoverflow.com/questions/2068804/why-is-string-final-in-java
Thomas Owens

ในทำนองเดียวกันสิ่งที่จะเกิดขึ้นถ้าไม่ได้java.io.File finalโอ้มันไม่ใช่ คนเสพเวจมรรค
Tom Hawtin - tackline

1
จุดจบของอารยธรรมตะวันตกที่เรารู้จัก
Tulains Córdova

คำตอบ:


22

เหตุผลหลักคือความเร็ว: finalคลาสไม่สามารถขยายได้ซึ่งอนุญาตให้ JIT ทำการปรับแต่งทุกประเภทเมื่อจัดการสตริง - ไม่จำเป็นต้องตรวจสอบวิธีการแทนที่

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

นอกจากนี้นักประดิษฐ์ของรันไทม์ Java ต้องการทำผิดด้านความปลอดภัยเสมอ ความสามารถในการขยายสตริง (สิ่งที่ฉันมักทำใน Groovy เพราะสะดวกมาก) สามารถเปิดเวิร์มทั้งหมดได้ถ้าคุณไม่รู้ว่าคุณกำลังทำอะไรอยู่


2
มันเป็นคำตอบที่ไม่ถูกต้อง นอกเหนือจากการตรวจสอบตามข้อกำหนด JVM แล้ว HotSpot จะใช้finalเป็นการตรวจสอบอย่างรวดเร็วว่าวิธีการจะไม่ถูกแทนที่เมื่อทำการรวบรวมรหัส
Tom Hawtin - tackline

1
@ TomHawtin-tackline: การอ้างอิง?
Aaron Digulla

1
คุณดูเหมือนจะบอกเป็นนัยว่าความไม่สามารถเปลี่ยนแปลงได้และการเป็นคนสุดท้ายนั้นมีความเกี่ยวข้องกัน "อีกเหตุผลหนึ่งคือความปลอดภัยของเธรด: Immutables จะปลอดภัยเสมอเธรด b ... " เหตุผลที่วัตถุไม่เปลี่ยนรูปหรือไม่ได้เป็นเพราะวัตถุเหล่านั้นไม่สมบูรณ์
Tulains Córdova

1
นอกจากนี้คลาส String ยังไม่เปลี่ยนรูปโดยไม่คำนึงถึงfinalคำสำคัญในคลาส อาร์เรย์ของอักขระที่มีนั้นถือเป็นที่สุดทำให้ไม่เปลี่ยนรูป การทำให้คลาสตัวเองสุดท้ายปิดลูปเป็น @abl กล่าวถึงเนื่องจากไม่สามารถนำคลาสย่อยที่ไม่แน่นอนได้

1
@Snowman เพื่อความแม่นยำอาร์เรย์ของอักขระที่ถูกทำให้สุดท้ายเท่านั้นที่ทำให้การอ้างอิงอาร์เรย์ไม่เปลี่ยนรูปไม่ใช่เนื้อหาของอาร์เรย์
Michał Kosmulski

10

มีอีกเหตุผลที่StringคลาสJava ต้องเป็นที่สิ้นสุด: มันเป็นสิ่งสำคัญสำหรับความปลอดภัยในบางสถานการณ์ หากStringคลาสไม่สุดท้ายรหัสต่อไปนี้จะมีความเสี่ยงต่อการถูกโจมตีโดยผู้โทรที่เป็นอันตราย

 public String makeSafeLink(String url, String text) {
     if (!url.startsWith("http:") && !url.startsWith("https:"))
         throw SecurityException("only http/https URLs are allowed");
     return "<a href=\"" + escape(url) + "\">" + escape(text) + "</a>";
 }

การโจมตี: ผู้เรียกที่ประสงค์ร้ายสามารถสร้างคลาสย่อยของ String EvilStringซึ่งEvilString.startsWith()จะส่งกลับค่าจริงเสมอ แต่ค่าของEvilStringสิ่งที่ชั่วร้าย (เช่นjavascript:alert('xss')) เนื่องจากคลาสย่อยนี้จะหลีกเลี่ยงการตรวจสอบความปลอดภัย การโจมตีนี้เรียกว่าช่องโหว่เวลาตรวจสอบเวลาใช้ (TOCTTOU): ระหว่างเวลาที่ตรวจสอบเสร็จแล้ว (URL เริ่มต้นด้วย http / https) และเวลาที่ใช้ค่า (เพื่อสร้างข้อมูลโค้ด HTML) ค่าที่มีประสิทธิภาพสามารถเปลี่ยนแปลงได้ หากStringยังไม่ถึงขั้นสุดท้ายความเสี่ยงของ TOCTTOU จะเป็นที่แพร่หลาย

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


แน่นอนว่ามันยังคงเป็นไปได้ที่จะดึง TOCTTOU คำรามออกมาโดยใช้การไตร่ตรองเพื่อแก้ไขchar[]ด้านในของสตริง แต่มันต้องใช้โชคในเวลา
Peter Taylor

2
@ Peter Taylor มันซับซ้อนกว่านั้น คุณสามารถใช้การสะท้อนเพื่อเข้าถึงตัวแปรส่วนตัวเท่านั้นหาก SecurityManager ให้สิทธิ์แก่คุณในการทำเช่นนั้น Applets และรหัสที่ไม่น่าเชื่อถืออื่น ๆ จะไม่ได้รับการอนุญาตนี้ดังนั้นจึงไม่สามารถใช้การสะท้อนกลับเพื่อแก้ไขความเป็นส่วนตัวchar[]ภายในสตริง ดังนั้นจึงไม่สามารถใช้ช่องโหว่ TOCTTOU ได้
DW

ฉันรู้ แต่ยังคงออกจากแอปพลิเคชันและแอปเพล็ตที่เซ็นชื่อ - และมีกี่คนที่กลัวโดยกล่องโต้ตอบคำเตือนสำหรับแอปเพล็ตที่ลงนามด้วยตนเอง
Peter Taylor

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

"การโจมตี: ผู้โทรที่เป็นอันตรายสามารถสร้างคลาสย่อยของ String, EvilString โดยที่ EvilString.startsWith () จะส่งกลับค่าจริงเสมอ ... " - ไม่ใช่ถ้า startsWith () ถือเป็นที่สิ้นสุด
Erik

4

หากไม่ใช่แอปพลิเคชัน Java แบบมัลติเธรดจะเป็นระเบียบ (ยิ่งกว่าสิ่งที่เป็นจริง)

IMHO ข้อได้เปรียบที่สำคัญที่สุดของสตริงสุดท้าย (ไม่เปลี่ยนรูป) ก็คือพวกเขามีความปลอดภัยในเธรด: พวกเขาไม่ต้องการการซิงโครไนซ์ (บางครั้งการเขียนโค้ดนั้นค่อนข้างไม่สำคัญ หากสิ่งเหล่านี้ไม่แน่นอนรับประกันสิ่งต่าง ๆ เช่นชุดเครื่องมือ windows แบบมัลติเธรดจะยากมากและสิ่งเหล่านั้นจำเป็นอย่างยิ่ง


3
finalคลาสไม่เกี่ยวข้องกับความผันแปรของคลาส

คำตอบนี้ไม่ได้ตอบคำถาม -1
FUZxxl

3
Jarrod Roberson: ถ้าชั้นเรียนไม่จบคุณสามารถสร้าง Strable ที่ไม่แน่นอนโดยใช้การสืบทอด
ysdx

@JarrodRoberson ในที่สุดก็มีคนสังเกตเห็นข้อผิดพลาด คำตอบที่ได้รับการยอมรับยังหมายถึงขั้นสุดท้ายเท่ากับไม่เปลี่ยนรูป
Tulains Córdova

1

ข้อดีอีกอย่างของการStringเป็นที่สิ้นสุดก็คือมันช่วยให้มั่นใจผลลัพธ์ที่คาดการณ์ได้เช่นเดียวกับที่ไม่สามารถเปลี่ยนแปลงได้ Stringแม้ว่าคลาสจะหมายถึงการปฏิบัติในบางสถานการณ์เช่นประเภทค่า (คอมไพเลอร์ยังสนับสนุนผ่านString blah = "test") ดังนั้นหากคุณสร้างสตริงที่มีค่าบางอย่างคุณคาดหวังว่ามันจะมีพฤติกรรมบางอย่างที่สืบทอดมาจากสตริงใด ๆ ซึ่งคล้ายกับความคาดหวังที่คุณมีกับจำนวนเต็ม

คิดว่าเรื่องนี้: เกิดอะไรขึ้นถ้าคุณย่อยชั้นjava.lang.Stringและมากกว่าขี่ม้าequalsหรือhashCodeวิธีการ? ทันใดนั้น "ทดสอบ" สองสายไม่สามารถเทียบเคียงกันได้

ลองนึกภาพความโกลาหลถ้าฉันทำได้:

public class Password extends String {
    public Password(String text) {
        super(text);
    }

    public boolean equals(Object o) {
        return true;
    }
}

ชั้นอื่น ๆ :

public boolean isRightPassword(String suppliedString) {
    return suppliedString != null && suppliedString.equals("secret");
}

public void login(String username, String password) {
    return isRightUsername(username) && isRightPassword(password);
}

public void loginTest() {
    boolean success = login("testuser", new Password("wrongpassword"));
    // success is true, despite the password being wrong
}

1

พื้นหลัง

มีสามที่สุดท้ายที่สามารถแสดงใน Java:

การทำให้คลาสสุดท้ายป้องกันคลาสย่อยทั้งหมดของคลาส ทำให้วิธีสุดท้ายป้องกันคลาสย่อยของวิธีการเอาชนะมัน การทำให้ฟิลด์สุดท้ายป้องกันไม่ให้มีการเปลี่ยนแปลงในภายหลัง

ความเข้าใจผิด

มีการเพิ่มประสิทธิภาพที่เกิดขึ้นรอบ ๆ วิธีการและเขตข้อมูลสุดท้าย

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

ตัวแปรสุดท้ายสามารถเพิ่มประสิทธิภาพในเชิงรุกและเพิ่มเติมเกี่ยวกับการที่สามารถอ่านได้ในส่วน JLS 17.5.3

แต่ด้วยความเข้าใจอย่างใดอย่างหนึ่งควรจะตระหนักว่าค่าการเพิ่มประสิทธิภาพเหล่านี้จะเกี่ยวกับการทำชั้นสุดท้าย ไม่มีการเพิ่มประสิทธิภาพโดยการทำให้ชั้นเรียนสุดท้าย

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

การออกแบบขั้นสุดท้าย

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

แผนที่

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

พิจารณารหัสสมมุตินี้:

Map t = new TreeMap<String, Integer>();
Map h = new HashMap<String, Integer>();
MyString one = new MyString("one");
MyString two = new MyString("two");

t.put(one, 1); h.put(one, 1);
t.put(two, 2); h.put(two, 2);

one.prepend("z");

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

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

คุณอาจสนใจอ่านทำไม String ถึงไม่เปลี่ยนแปลงใน Java? สำหรับข้อมูลเพิ่มเติมเกี่ยวกับลักษณะที่ไม่เปลี่ยนแปลงของ Strings

สตริงชั่วร้าย

มีตัวเลือกที่ชั่วร้ายมากมายสำหรับ Strings ลองพิจารณาว่าฉันสร้างสตริงที่มักจะคืนค่าจริงเมื่อมีการเรียก ... และส่งผ่านการตรวจสอบรหัสผ่านหรือไม่ หรือทำเพื่อที่การมอบหมายให้ MyString จะส่งสำเนาของ String ไปยังที่อยู่อีเมลบางอัน?

สิ่งเหล่านี้เป็นไปได้จริงมากเมื่อคุณมีความสามารถในการซับสตริงคลาส

การเพิ่มประสิทธิภาพสตริง Java.lang

ในขณะที่ก่อนหน้านี้ฉันพูดถึงว่าขั้นตอนสุดท้ายจะไม่ทำให้ String เร็วขึ้น อย่างไรก็ตามคลาส String (และคลาสอื่น ๆ ในjava.lang) ใช้การป้องกันระดับแพ็กเกจของฟิลด์และวิธีการเพื่ออนุญาตให้java.langคลาสอื่น ๆสามารถใช้งาน tinker กับ internals แทนการผ่าน API สาธารณะสำหรับ String ตลอดเวลา ฟังก์ชั่นเช่นgetCharsโดยไม่มีการตรวจสอบช่วงหรือlastIndexOfที่ใช้โดย StringBuffer หรือตัวสร้างที่แชร์อาเรย์พื้นฐาน (โปรดทราบว่าเป็นสิ่ง Java 6 ที่มีการเปลี่ยนแปลงเนื่องจากปัญหาหน่วยความจำ)

หากมีคนสร้างคลาสย่อยของ String มันจะไม่สามารถแบ่งปันการปรับปรุงเหล่านั้นได้ (เว้นแต่จะเป็นส่วนหนึ่งของjava.langด้วย แต่เป็นแพ็คเกจที่ปิดผนึก )

มันยากที่จะออกแบบบางสิ่งเพื่อขยาย

การออกแบบสิ่งที่จะขยายเป็นเรื่องยาก หมายความว่าคุณต้องเปิดเผยบางส่วนของ internals ของคุณเพื่อให้สามารถแก้ไขได้

สตริงที่ขยายได้อาจไม่มีการแก้ไขหน่วยความจำรั่ว ส่วนเหล่านั้นจะต้องได้รับการสัมผัสกับคลาสย่อยและการเปลี่ยนรหัสนั้นจะหมายถึงคลาสย่อยจะแตก

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

Checkstyleมีกฎที่บังคับใช้ (ซึ่งทำให้ฉันหงุดหงิดจริงๆเมื่อเขียนโค้ดภายใน) เรียกว่า "DesignForExtension" ซึ่งบังคับให้ทุกคลาสเป็น:

  • บทคัดย่อ
  • สุดท้าย
  • การใช้งานที่ว่างเปล่า

เหตุผลที่:

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

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

นักพัฒนา hurbis

ส่วนหนึ่งของการเป็นนักพัฒนา พิจารณาความเป็นไปได้ที่นักพัฒนาแต่ละคนจะสร้าง subclass สตริงของตัวเองกับคอลเลกชันของตัวเองutilsในนั้น แต่ตอนนี้คลาสย่อยเหล่านี้ไม่สามารถมอบหมายให้กันและกันได้อย่างอิสระ

WleaoString foo = new WleaoString("foo");
MichaelTString bar = foo; // This doesn't work.

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

ฉันแน่ใจว่าคุณสามารถเขียน string คลาสดี ... แต่ปล่อยให้การเขียนการใช้งานหลายสตริงกับคนบ้าผู้ที่เขียน C ++ และมีการจัดการกับstd::stringและchar*และอะไรบางอย่างจากการเพิ่มและSStringและส่วนที่เหลือทั้งหมด

จาวาสตริงเวทมนตร์

มีสิ่งมหัศจรรย์หลายอย่างที่ Java ทำกับ Strings สิ่งเหล่านี้ทำให้โปรแกรมเมอร์จัดการได้ง่ายขึ้น แต่แนะนำความไม่สอดคล้องของภาษา การอนุญาตให้คลาสย่อยใน String ใช้ความคิดที่สำคัญมากเกี่ยวกับวิธีจัดการกับสิ่งมหัศจรรย์เหล่านี้:

  • สตริงตัวอักษร (JLS 3.10.5 )

    มีรหัสที่อนุญาตให้ทำ:

    String foo = "foo";

    นี่ไม่ควรสับสนกับชกมวยประเภทตัวเลขเช่นจำนวนเต็ม คุณไม่สามารถทำแต่คุณสามารถทำได้1.toString()"foo".concat(bar)

  • +ประกอบการ (JLS 15.18.1 )

    ไม่มีประเภทการอ้างอิงอื่นใน Java ที่อนุญาตให้ผู้ปฏิบัติงานใช้งาน เชือกเป็นพิเศษ ตัวดำเนินการเชื่อมต่อสตริงยังทำงานที่ระดับคอมไพเลอร์เพื่อที่"foo" + "bar"จะกลายเป็น"foobar"เมื่อมันถูกรวบรวมมากกว่าที่รันไทม์

  • การแปลงสตริง (JLS 5.1.11 )

    วัตถุทั้งหมดสามารถแปลงเป็นสตริงได้โดยใช้พวกมันในบริบทของสตริง

  • การใช้สตริง ( JavaDoc )

    คลาส String มีการเข้าถึงพูลของสตริงที่อนุญาตให้มีการรับรองแบบบัญญัติของวัตถุซึ่งถูกเติมด้วยชนิดคอมไพล์ด้วยตัวอักษรสตริง

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


0

หาก String ไม่เป็นที่สิ้นสุดหน้าอกเครื่องมือของโปรแกรมเมอร์ทุกคนจะมี "String ที่มีวิธีการช่วยเหลือที่ดีเพียงไม่กี่ตัว" แต่ละเหล่านี้จะไม่เข้ากันกับหีบเครื่องมืออื่น ๆ ทั้งหมด

ฉันคิดว่ามันเป็นข้อ จำกัด ที่โง่ วันนี้ฉันเชื่อว่านี่เป็นการตัดสินใจที่ดีมาก มันทำให้สตริงเป็นสตริง


finalใน Java ไม่เหมือนกับfinalใน C # ในบริบทนี้มันเป็นสิ่งเดียวกับ C # readonly's ดูstackoverflow.com/questions/1327544/…
Arseni Mourzenko

9
@MainMa: ที่จริงในบริบทนี้ดูเหมือนว่ามันเหมือนเป็น C # 's public final class Stringปิดผนึกในขณะที่
กำหนดค่า
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.