CodeGym /จาวาบล็อก /สุ่ม /พูดคุยเกี่ยวกับคำหลักสุดท้ายใน Java
John Squirrels
ระดับ
San Francisco

พูดคุยเกี่ยวกับคำหลักสุดท้ายใน Java

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

    public final class String {
    }
    
    class SubString extends String { // Compilation error
    }
ฉันควรทราบด้วยว่าตัวแก้ไขสุดท้ายไม่สามารถใช้กับคลาสนามธรรม (ที่มีคำหลักนามธรรม) เนื่องจากสิ่งเหล่านี้เป็นแนวคิดที่พิเศษร่วมกัน สำหรับเมธอดสุดท้าย โมดิฟายเออร์หมายความว่าเมธอดไม่สามารถแทนที่ในคลาสย่อยได้ สิ่งนี้มีประโยชน์เมื่อเราต้องการป้องกันไม่ให้เกิดการเปลี่ยนแปลงของการใช้งานดั้งเดิม

    public class SuperClass {
        public final void printReport() {
            System.out.println("Report");
        }
    }

    class SubClass extends SuperClass { 
        public void printReport() { //Compilation error
            System.out.println("MyReport");
        }
    }
สำหรับตัวแปรประเภทดั้งเดิม คีย์เวิร์ดสุดท้ายหมายความว่าค่าที่กำหนดให้แล้วจะไม่สามารถเปลี่ยนแปลงได้ สำหรับตัวแปรอ้างอิง หมายความว่าหลังจากกำหนดวัตถุแล้ว คุณไม่สามารถเปลี่ยนการอ้างอิงไปยังวัตถุนั้นได้ นี้เป็นสิ่งสำคัญ! การอ้างอิงไม่สามารถเปลี่ยนแปลงได้ แต่สถานะของวัตถุสามารถเปลี่ยนแปลงได้ Java 8 นำเสนอแนวคิดใหม่: ขั้นสุดท้ายอย่างมีประสิทธิภาพ ใช้กับตัวแปรเท่านั้น (รวมถึงพารามิเตอร์เมธอด) บรรทัดล่างคือแม้ว่าจะไม่มีคำหลักสุดท้ายอย่างชัดเจน แต่ค่าของตัวแปรจะไม่เปลี่ยนแปลงหลังจากเริ่มต้น กล่าวอีกนัยหนึ่ง สามารถใช้คำหลักสุดท้ายกับตัวแปรดังกล่าวได้โดยไม่มีข้อผิดพลาดในการคอมไพล์ ตัวแปรสุดท้ายอย่างมีประสิทธิภาพสามารถใช้ได้ภายในคลาสโลคัล (คลาสภายในโลคัล) คลาสนิรนาม (คลาสภายในนิรนาม) และสตรีม (Stream API)

        public void someMethod() {
            // In the example below, both a and b are effectively final, since they are assigned values only once:
            int a = 1;
            int b;
            if (a == 2) b = 3;
            else b = 4;
            // c is NOT effectively final since its value changes
            int c = 10;
            c++;
            
            Stream.of(1, 2).forEach(s-> System.out.println(s + a)); // OK
            Stream.of(1, 2).forEach(s-> System.out.println(s + c)); // Compilation error
        }
เอาล่ะ มาสัมภาษณ์กันหน่อยดีกว่า ท้ายที่สุดแล้ว เป้าหมายของการจบหลักสูตร CodeGym ก็คือการเป็นนักพัฒนา Java และหางานที่น่าสนใจและได้ค่าตอบแทนดี มาเริ่มกันเลย
  1. เราจะพูดอะไรเกี่ยวกับอาร์เรย์ที่ประกาศขั้นสุดท้ายได้บ้าง

  2. เรารู้ว่าคลาส String นั้นเปลี่ยนรูปไม่ได้: คลาสนั้นถูกประกาศเป็นขั้นสุดท้าย ค่าสตริงถูกเก็บไว้ในอาร์เรย์ถ่านที่ทำเครื่องหมายด้วยคำหลักสุดท้าย


public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

เราสามารถแทนที่ค่าของวัตถุ String (โดยไม่เปลี่ยนการอ้างอิงไปยังวัตถุ) ได้หรือไม่ นี่เป็นคำถามสัมภาษณ์จริง และการปฏิบัติแสดงให้เห็นว่าผู้สมัครจำนวนมากตอบคำถามไม่ถูกต้อง การทำความเข้าใจวิธีใช้คำหลักขั้นสุดท้าย โดยเฉพาะอย่างยิ่งสำหรับตัวแปรอ้างอิง มีความสำคัญมาก ในขณะที่คุณพิจารณาเรื่องนี้ ฉันจะส่งคำขอเล็กน้อยไปยังทีม CodeGym โปรดให้สิทธิ์แก่โปรแกรมแก้ไขข้อความในการเพิ่มบล็อกที่สามารถแสดง/ซ่อนเนื้อหาได้เมื่อคุณคลิก คำตอบ:
  1. อาร์เรย์เป็นวัตถุ ดังนั้นคำหลักสุดท้ายหมายความว่าเมื่อกำหนดการอ้างอิงไปยังอาร์เรย์แล้ว การอ้างอิงนั้นจะไม่สามารถเปลี่ยนแปลงได้ ที่กล่าวว่า คุณสามารถเปลี่ยนสถานะของวัตถุ

    
            final int[] array = {1, 2, 3, 4, 5};
            array[0] = 9;	 // OK, because we're changing the contents of the array: {9, 2, 3, 4, 5}
            array = new int[5]; // Compilation error
    
  2. ใช่เราทำได้ สิ่งสำคัญคือต้องเข้าใจว่าคำหลักสุดท้ายที่มีหนามหมายถึงอะไรเมื่อใช้กับอ็อบเจกต์ สามารถใช้ Reflection API เพื่อแทนที่ค่าต่างๆ


import java.lang.reflect.Field;

class B {
    public static void main(String[] args) throws Exception {
        String value = "Old value";
        System.out.println(value);

        // Get the String class's value field
        Field field = value.getClass().getDeclaredField("value");
        // Make it mutable
        field.setAccessible(true);
        // Set a new value
        field.set(value, "CodeGym".toCharArray());

        System.out.println(value);

        /* Output:
         * Old value
         * CodeGym
         */
    }
}
โปรดทราบว่าหากเราพยายามเปลี่ยนตัวแปรสุดท้ายของประเภทดั้งเดิมด้วยวิธีนี้ ก็จะไม่มีอะไรเกิดขึ้น ฉันขอแนะนำให้คุณโน้มน้าวใจตัวเอง: สร้างคลาส Java ด้วยฟิลด์ int สุดท้ายและลองเปลี่ยนค่าโดยใช้ Reflection API โชคดีทุกคน!
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION