โค้ดยิม/จาวาบล็อก/สุ่ม/พูดคุยเกี่ยวกับคำหลักสุดท้ายใน 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 โชคดีทุกคน!
ความคิดเห็น
  • เป็นที่นิยม
  • ใหม่
  • เก่า
คุณต้องลงชื่อเข้าใช้เพื่อแสดงความคิดเห็น
หน้านี้ยังไม่มีความคิดเห็นใด ๆ