0Pricing
Java Academy · บทเรียน

เหตุใด String จึงเปลี่ยนแปลงไม่ได้

ทำความเข้าใจการเปลี่ยนแปลงไม่ได้ของ String

เหตุใด String จึงเปลี่ยนแปลงไม่ได้ เป็นบทเรียน Java Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Java Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน

สตริงเปลี่ยนแปลงไม่ได้

ใน Java สตริงเป็นสิ่งที่เปลี่ยนแปลงไม่ได้: เมื่อสร้างแล้ว อักขระภายในจะเปลี่ยนแปลงไม่ได้อีก เมธอดใดก็ตามที่ดูเหมือนจะแก้ไขสตริง แท้จริงแล้วจะส่งคืนสตริงใหม่ทั้งชุด

เมธอดส่งคืนสตริงใหม่

toUpperCase() replace() และเมธอดอื่น ๆ ที่คล้ายกันจะไม่แก้ไขค่าเดิม แต่จะสร้าง String ใหม่และปล่อยให้ค่าเดิมไม่เปลี่ยนแปลง

public class Main {
    public static void main(String[] args) {
        String original = "hello";
        String upper = original.toUpperCase();
        System.out.println("original: " + original);
        System.out.println("upper: " + upper);
    }
}

การกำหนดค่าใหม่ไม่ใช่การเปลี่ยนแปลงค่าเดิม

เมื่อเขียน s = s + "!" ตัวแปรจะชี้ไปยังสตริงใหม่ ส่วนออบเจ็กต์สตริงเดิมยังไม่เปลี่ยนแปลง และอาจถูกตัวเก็บขยะเก็บคืน

public class Main {
    public static void main(String[] args) {
        String s = "hi";
        String firstRef = s;
        s = s + "!";
        System.out.println("s: " + s);
        System.out.println("firstRef: " + firstRef);
    }
}

เหตุใดจึงต้องเปลี่ยนแปลงไม่ได้

การเปลี่ยนแปลงไม่ได้มีประโยชน์จริงหลายประการ:

  • ความปลอดภัยต่อเธรด: สามารถใช้สตริงร่วมกันได้โดยไม่ต้องใช้ล็อก
  • การแคช: รหัสแฮชและรายการในพูลยังคงถูกต้อง
  • ความปลอดภัย: สตริงที่ส่งให้เมธอดจะไม่ถูกเปลี่ยนแปลงโดยที่คุณไม่รู้ตัว

พูลสตริง

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

public class Main {
    public static void main(String[] args) {
        String a = "java";
        String b = "java";
        System.out.println(a == b);
        System.out.println(a.equals(b));
    }
}

การสร้างสตริงใหม่ทำให้ไม่ใช้พูลร่วมกัน

การใช้ new String(...) จะบังคับให้สร้างออบเจ็กต์แยกต่างหาก ดังนั้นการเปรียบเทียบการอ้างอิงจึงให้ผลต่างกัน แม้เนื้อหาจะเหมือนกันก็ตาม ควรเปรียบเทียบเนื้อหาด้วย equals เสมอ

public class Main {
    public static void main(String[] args) {
        String a = "java";
        String b = new String("java");
        System.out.println("== : " + (a == b));
        System.out.println("equals: " + a.equals(b));
    }
}

ต้นทุนของการต่อสตริง

การใช้ + กับสตริงแต่ละครั้งจะสร้างออบเจ็กต์ใหม่ หากทำเช่นนี้ในลูป จะจัดสรรสตริงอายุสั้นจำนวนมาก ทำให้เสียเวลาและหน่วยความจำ

public class Main {
    public static void main(String[] args) {
        String result = "";
        for (int i = 1; i <= 5; i++) {
            result = result + i;
        }
        System.out.println(result);
    }
}

การเติบโตแบบกำลังสอง

เนื่องจากการต่อแต่ละครั้งจะคัดลอกอักขระทั้งหมดที่มีอยู่ก่อนหน้า การสร้างสตริงยาวด้วย + ในลูปจึงมีประสิทธิภาพลดลงอย่างมากเมื่อขนาดเพิ่มขึ้น โดยมีลักษณะใกล้เคียง O(n กำลังสอง) นี่คือปัญหาด้านประสิทธิภาพหลัก

public class Main {
    public static void main(String[] args) {
        String s = "";
        for (int i = 0; i < 1000; i++) {
            s += "x";
        }
        System.out.println("Length: " + s.length());
    }
}

ค่าที่เปลี่ยนแปลงไม่ได้ให้ผลคาดเดาได้

การส่งสตริงให้เมธอดนั้นปลอดภัย เพราะเมธอดไม่สามารถเปลี่ยนสำเนาของคุณได้ ในตัวอย่างนี้เมธอดสร้างสตริงใหม่ และค่าของผู้เรียกยังคงเดิม

public class Main {
    static void shout(String s) {
        s = s + "!!!";
        System.out.println("inside: " + s);
    }
    public static void main(String[] args) {
        String msg = "hello";
        shout(msg);
        System.out.println("outside: " + msg);
    }
}

เกริ่นนำวิธีแก้ปัญหา

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

public class Main {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder();
        for (int i = 1; i <= 5; i++) {
            sb.append(i);
        }
        System.out.println(sb.toString());
    }
}

เปรียบเทียบสองแนวทาง

สำหรับการต่อสตริงเพียงไม่กี่ครั้ง + ใช้งานได้ดีและอ่านง่าย แต่หากทำหลายครั้งในลูป ควรเลือกใช้ StringBuilder ให้พิจารณาจากปริมาณข้อความที่ต้องสร้าง

public class Main {
    public static void main(String[] args) {
        String simple = "a" + "b" + "c";
        StringBuilder sb = new StringBuilder("a");
        sb.append("b").append("c");
        System.out.println(simple);
        System.out.println(sb);
    }
}

ตรวจสอบอย่างรวดเร็ว

เมื่อเรียกใช้ s.toUpperCase() กับ String จะเกิดอะไรขึ้นจริง

ทบทวน

คุณได้เรียนรู้ว่าเหตุใดสตริงจึงเปลี่ยนแปลงไม่ได้:

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

คำถามที่พบบ่อย

บทเรียน “เหตุใด String จึงเปลี่ยนแปลงไม่ได้” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “เหตุใด String จึงเปลี่ยนแปลงไม่ได้” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Java Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “เหตุใด String จึงเปลี่ยนแปลงไม่ได้”

ทำความเข้าใจการเปลี่ยนแปลงไม่ได้ของ String คุณปฏิบัติ Java Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Java Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Java Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน

บทเรียน “เหตุใด String จึงเปลี่ยนแปลงไม่ได้” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Java Academy นี้ได้ไหม

ได้ บทเรียน Java Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. เหตุใด String จึงเปลี่ยนแปลงไม่ได้
  2. การสร้างข้อความด้วย StringBuilder
  3. เมธอดของ StringBuilder
  4. StringBuilder เทียบกับ StringBuffer
← กลับไปที่ Java Academy