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 และหางานที่น่าสนใจและได้ค่าตอบแทนดี มาเริ่มกันเลย
-
เราจะพูดอะไรเกี่ยวกับอาร์เรย์ที่ประกาศขั้นสุดท้ายได้บ้าง
-
เรารู้ว่าคลาส 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 โปรดให้สิทธิ์แก่โปรแกรมแก้ไขข้อความในการเพิ่มบล็อกที่สามารถแสดง/ซ่อนเนื้อหาได้เมื่อคุณคลิก คำตอบ:
-
อาร์เรย์เป็นวัตถุ ดังนั้นคำหลักสุดท้ายหมายความว่าเมื่อกำหนดการอ้างอิงไปยังอาร์เรย์แล้ว การอ้างอิงนั้นจะไม่สามารถเปลี่ยนแปลงได้ ที่กล่าวว่า คุณสามารถเปลี่ยนสถานะของวัตถุ
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
-
ใช่เราทำได้ สิ่งสำคัญคือต้องเข้าใจว่าคำหลักสุดท้ายที่มีหนามหมายถึงอะไรเมื่อใช้กับอ็อบเจกต์ สามารถใช้ 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 โชคดีทุกคน!
GO TO FULL VERSION