เมื่อประกาศคุณสมบัติวิธีการและคลาสใน Java คำหลักสุดท้ายสามารถใช้ในการแก้ไขได้ ตัวแปรสุดท้ายเป็นค่าคงที่และสามารถกำหนดได้เพียงครั้งเดียวเท่านั้น วิธีสุดท้ายไม่สามารถเขียนใหม่ได้โดยคลาสย่อย; คลาสสุดท้ายไม่สามารถสืบทอดได้
1. สมาชิกสุดท้าย
การประกาศฟิลด์สุดท้ายช่วยให้เครื่องมือเพิ่มประสิทธิภาพตัดสินใจเพิ่มประสิทธิภาพได้ดีขึ้นเพราะหากคอมไพเลอร์รู้ว่าค่าของฟิลด์จะไม่เปลี่ยนแปลงมันสามารถแคชค่าในการลงทะเบียนได้อย่างปลอดภัย ฟิลด์สุดท้ายยังให้ระดับความปลอดภัยเพิ่มเติมโดยให้คอมไพเลอร์บังคับให้ฟิลด์เป็นแบบอ่านอย่างเดียว
1.1 เกี่ยวกับการกำหนดสมาชิกขั้นสุดท้าย
1) ใน Java ตัวแปรธรรมดาสามารถเริ่มต้นได้โดยค่าเริ่มต้น แต่ตัวแปรประเภทสุดท้ายจะต้องเริ่มต้นอย่างชัดเจน
2) สมาชิกขั้นสุดท้ายสามารถและสามารถเริ่มต้นได้เพียงครั้งเดียว
3) สมาชิกขั้นสุดท้ายจะต้องเริ่มต้นที่การประกาศ (กำหนดค่าโดยตรงไปยังตัวแปรสุดท้ายเมื่อมีการกำหนด) หรือในตัวสร้างและไม่สามารถเริ่มต้นได้ที่อื่น
ตัวอย่าง 1 bat.java
BAT ชั้นเรียนสาธารณะ {Final Double Pi = 3.14; // กำหนด int สุดท้ายฉันเมื่อกำหนด; // เนื่องจากจะต้องเริ่มต้นในตัวสร้างรายการสุดท้าย <bat> รายการไม่สามารถกำหนดได้ที่นี่ // เนื่องจากจะต้องเริ่มต้นในตัวสร้าง BAT () ไม่สามารถกำหนดได้ที่นี่ {i = 100; list = new LinkedList <bat> (); } bat (int ii, รายการ <bat> l) {i = ii; รายการ = l; } โมฆะคงที่สาธารณะหลัก (สตริง [] args) {bat b = ค้างคาวใหม่ (); b.list.add (ค้างคาวใหม่ ()); // bi = 25; // b.list = new ArrayList <bat> (); System.out.println ("i =" + bi + "ประเภทรายการ:" + b.list.getClass ()); b = ค้างคาวใหม่ (23, arraylist ใหม่ <bat> ()); b.list.add (ค้างคาวใหม่ ()); System.out.println ("i =" + bi + "ประเภทรายการ:" + b.list.getClass ()); -
ผลลัพธ์:
i = 100 รายการประเภท: คลาส java.util.linkedlisti = 23 รายการประเภท: คลาส java.util.arraylist
มีคำสั่งสองบรรทัดในวิธีหลักที่แสดงความคิดเห็น หากคุณลบความคิดเห็นโปรแกรมจะไม่สามารถรวบรวมได้ ซึ่งหมายความว่าไม่ว่าจะเป็นค่าของ I หรือประเภทของรายการเมื่อเริ่มต้นแล้วก็ไม่สามารถเปลี่ยนแปลงได้ อย่างไรก็ตาม B สามารถระบุค่าของ I หรือประเภทของรายการโดยการปรับเปลี่ยนใหม่
1.2 การเริ่มต้นที่ไม่ถูกต้องของฟิลด์อ้างอิงสุดท้าย
มันค่อนข้างลำบากในการใช้ฟิลด์สุดท้ายอย่างถูกต้องโดยเฉพาะอย่างยิ่งสำหรับการอ้างอิงวัตถุที่ผู้สร้างสามารถโยนข้อยกเว้นได้ เนื่องจากฟิลด์สุดท้ายจะต้องเริ่มต้นเพียงครั้งเดียวในแต่ละตัวสร้างหากคอนสตรัคเตอร์ที่อ้างอิงโดยวัตถุสุดท้ายอาจโยนข้อยกเว้นคอมไพเลอร์อาจรายงานข้อผิดพลาดที่บอกว่าฟิลด์ไม่ได้เริ่มต้น คอมไพเลอร์โดยทั่วไปฉลาดพอที่จะพบว่าการเริ่มต้นในแต่ละสาขาของสองรหัส mutex (เช่นถ้า ... บล็อกอื่น) เกิดขึ้นเพียงครั้งเดียว แต่มักจะไม่ "ให้อภัย" เพื่อลอง ... จับบล็อก
รหัสต่อไปนี้มักจะมีปัญหา
Class Thingie {Public Static Thingie GetDefaultThingie () {return new Thingie (); }} คลาสสาธารณะ foo {สิ่งสุดท้ายของสิ่งสุดท้ายสิ่งสุดท้าย; public foo () {ลอง {thingie = new Thingie (); } catch (Exception e) {thingie = thingie.getDefaultTHINGIE (); // ข้อผิดพลาด: FIELD FIELD THETIE อาจได้รับมอบหมายไว้แล้ว}}}}
คุณสามารถแก้ไขสิ่งนี้ได้
ชั้นเรียนสาธารณะ foo {สิ่งสุดท้ายของสิ่งสุดท้ายสิ่งสุดท้าย; public foo () {Thingie Tempthingie; ลอง {tempThingie = new Thingie (); } catch (exception e) {tempThingie = thingie.getDefaultTHINGIE (); } thingie = tempthingie; -
1.3 เกี่ยวกับการใช้งานขั้นสุดท้าย
เมื่อคุณกำหนดตัวแปรในคลาสให้เพิ่มคำหลักสุดท้ายก่อนหน้านี้นั่นหมายความว่าเมื่อตัวแปรนี้เริ่มต้นแล้วจะไม่สามารถเปลี่ยนแปลงได้ ความหมายของความไม่สามารถเปลี่ยนแปลงได้ที่นี่คือค่าของมันไม่เปลี่ยนรูปสำหรับประเภทพื้นฐานและการอ้างอิงไม่สามารถเปลี่ยนแปลงได้อีกต่อไปสำหรับตัวแปรวัตถุ อย่างไรก็ตามวัตถุเองสามารถแก้ไขได้และ Java ไม่ได้ให้วิธีการทำให้วัตถุใด ๆ คงที่ ข้อ จำกัด นี้ยังเหมาะกับอาร์เรย์ซึ่งเป็นวัตถุ
ตัวอย่างที่ 2
ส่วนตัวสุดท้าย int val_one = 9; int สุดท้ายคงที่ int val_two = 99; int สุดท้ายคงที่ int val_three = 999;
เนื่องจาก val_one และ val_tow เป็นประเภทดั้งเดิมสุดท้ายที่มีค่าคอมไพล์เวลาทั้งสองจึงสามารถใช้เป็นค่าคงที่เวลารวบรวมและไม่มีความแตกต่างอย่างมีนัยสำคัญ Val_three เป็นวิธีทั่วไปในการกำหนดค่าคงที่: กำหนดเป็นสาธารณะสามารถใช้นอกแพ็คเกจได้ นิยามว่าเป็นแบบคงที่เพื่อเน้นเพียงหนึ่งสำเนา; กำหนดเป็นขั้นสุดท้ายเพื่อระบุว่าเป็นค่าคงที่
ตัวแปรที่ทำเครื่องหมายไว้สุดท้ายจะกลายเป็นค่าคงที่ แต่ "ค่าคงที่" นี้สามารถใช้ได้ภายในคลาสนี้เท่านั้นและไม่สามารถใช้โดยตรงนอกชั้นเรียน อย่างไรก็ตามเมื่อเราใช้การคงที่สาธารณะสุดท้ายเพื่อทำเครื่องหมายค่าคงที่ค่าคงที่นี้จะกลายเป็นค่าคงที่ระดับโลก (ฟิลด์ที่มีทั้งแบบคงที่และสุดท้ายจะครอบครองพื้นที่เก็บของที่ไม่สามารถเปลี่ยนแปลงได้) ยิ่งไปกว่านั้นค่าคงที่ที่กำหนดไว้ในวิธีนี้สามารถกำหนดค่าได้เมื่อกำหนดเท่านั้นและไม่มีสถานที่อื่น ๆ ที่สามารถทำได้
ตัวอย่างที่ 3
ค่าคลาส {int i; ค่าสาธารณะ (int i) {this.i = i; }} คลาสสาธารณะ FinalData {Private Static Random Rand = new Random (); รหัสสตริงส่วนตัว; Public FinalData (String ID) {this.id = id; } INT สุดท้ายส่วนตัว I4 = RAND.NEXTINT (20); int สุดท้ายคงที่ i5 = rand.nextint (20); สตริงสาธารณะ toString () {return id + ":" + "i4:" + i4 + ", i5 =" + i5; } โมฆะคงที่สาธารณะหลัก (สตริง [] args) {finalData fd1 = ใหม่ finalData ("fd1"); System.out.println (FD1); System.out.println ("การสร้าง FinalData ใหม่"); FinalData FD2 = New FinalData ("FD2"); System.out.println (FD1); System.out.println (FD2); -
ผลลัพธ์
fd1: i4: 6, i5 = 3 สร้างใหม่ FinalDatafd1: i4: 6, i5 = 3fd2: i4: 17, i5 = 3
ส่วนตัวอย่างแสดงความแตกต่างระหว่างการกำหนดค่าสุดท้ายเป็นแบบคงที่ (i5) และไม่คงที่ (I4) ความแตกต่างนี้จะปรากฏขึ้นเมื่อค่าเริ่มต้นในระหว่างการรันไทม์เนื่องจากคอมไพเลอร์ถือว่าค่าที่รวบรวมได้อย่างเท่าเทียมกัน (และพวกเขาอาจหายไปจากการเพิ่มประสิทธิภาพ) คุณจะเห็นความแตกต่างนี้เมื่อคุณเรียกใช้โปรแกรม โปรดทราบว่าใน FD1 และ FD2 ค่าของ i5 ไม่สามารถเปลี่ยนแปลงได้โดยการสร้างวัตถุ FinalData ที่สอง นี่เป็นเพราะมันคงที่ซึ่งเริ่มต้นที่การโหลดไม่ใช่ทุกครั้งที่มีการสร้างวัตถุใหม่
ตัวอย่างที่ 4
ค่าคลาส {int i; ค่าสาธารณะ (int i) {this.i = i; }} คลาสสาธารณะ… {ค่าส่วนตัว v1 = ค่าใหม่ (11); ค่าสุดท้ายส่วนตัว v2 = ค่าใหม่ (22); ค่าคงที่ส่วนตัวสุดท้าย V3 = ค่าใหม่ (33); …} โมฆะคงที่สาธารณะหลัก (สตริง [] args) {… fd1.v2.i ++; // ok-object ไม่คงที่! fd1.v1 = ค่าใหม่ (9); // ตกลง-ไม่สุดท้าย fd1.v2 = ค่าใหม่ (0); // ข้อผิดพลาด: ไม่สามารถเปลี่ยนการอ้างอิง fd1.v3 = ค่าใหม่ (1); // ข้อผิดพลาด: ไม่สามารถเปลี่ยนการอ้างอิง…} ตัวแปรจาก V1 ถึง V3 แสดงความหมายของการอ้างอิงขั้นสุดท้าย อย่างที่คุณเห็นใน Main () คุณไม่สามารถคิดได้ว่าคุณไม่สามารถเปลี่ยนค่าได้เพียงเพราะ V2 ถือเป็นที่สิ้นสุด เนื่องจากเป็นข้อมูลอ้างอิงขั้นสุดท้ายหมายความว่าคุณไม่สามารถชี้ V2 ไปยังวัตถุใหม่อื่นได้อีก
ตัวอย่างที่ 5
ชั้นเรียนสาธารณะ… {ส่วนตัวสุดท้าย int [] a = {1,2,3,4,5,5,6}; …} โมฆะคงที่สาธารณะหลัก (สตริง [] args) {…สำหรับ (int i = 0; i <fd1.a.length; i ++) fd1.a [i] ++; // ok-object ไม่คงที่! fd1.a = int ใหม่ [3]; // ข้อผิดพลาด: ไม่สามารถเปลี่ยนการอ้างอิง…} มีความหมายเดียวกันสำหรับอาร์เรย์ (สามารถเปลี่ยนค่าได้ แต่ไม่สามารถชี้ไปที่วัตถุใหม่) อาร์เรย์เป็นข้อมูลอ้างอิงอื่น
1.4 แก้ข้อ จำกัด ของอาร์เรย์สุดท้าย
แม้ว่าการอ้างอิงอาร์เรย์สามารถประกาศขั้นสุดท้ายได้ แต่องค์ประกอบของอาร์เรย์ก็ไม่สามารถทำได้ ซึ่งหมายความว่าทั้งชั้นเรียนที่เปิดเผยฟิลด์อาเรย์สุดท้ายของสาธารณะหรือส่งคืนการอ้างอิงไปยังฟิลด์เหล่านั้นผ่านวิธีการของพวกเขานั้นไม่แน่นอน
// ไม่เปลี่ยนรูป - อาร์เรย์ของรัฐสามารถแก้ไขได้โดยอันตราย // CallerPublicClass อันตราย {สตริงสุดท้ายส่วนตัว [] state = สตริงใหม่ [] {"Alabama", "Alaska", "ect"}; สตริงสาธารณะ [] getStates () {return state; -
ในทำนองเดียวกันแม้ว่าการอ้างอิงวัตถุสามารถประกาศเป็นฟิลด์สุดท้าย แต่วัตถุที่อ้างอิงอาจยังคงไม่แน่นอน หากคุณต้องการสร้างวัตถุที่ไม่แปรเปลี่ยนโดยใช้ฟิลด์สุดท้ายคุณต้องป้องกันการอ้างอิงถึงอาร์เรย์หรือวัตถุที่ไม่แน่นอนจาก "หลบหนี" คลาสของคุณ ในการทำสิ่งนี้โดยไม่ต้องโคลนอาร์เรย์ซ้ำ ๆ วิธีง่ายๆคือการแปลงอาร์เรย์เป็นรายการ
// immutable - ส่งคืนรายการที่ไม่สามารถแก้ไขได้แทน PublicClass ปลอดภัย {สตริงสุดท้ายส่วนตัว [] state = new String [] {"Alabama", "Alaska", "ect"}; รายการสุดท้ายรายการสุดท้าย stateSlist = new AbstractList () {วัตถุสาธารณะได้รับ (int n) {return state [n]; } ขนาด int สาธารณะ () {return state.length; - รายการสาธารณะ getStates () {return stateaslist; -
1.5 เกี่ยวกับการใช้พารามิเตอร์สุดท้าย
การใช้งานอีกอย่างคือการกำหนดพารามิเตอร์ในวิธีสุดท้าย สำหรับตัวแปรประเภทพื้นฐานสิ่งนี้ไม่มีความสำคัญในทางปฏิบัติใด ๆ เนื่องจากตัวแปรของประเภทพื้นฐานการส่งผ่านเมื่อเรียกวิธีการนั่นคือคุณสามารถเปลี่ยนตัวแปรพารามิเตอร์ในวิธีการโดยไม่ส่งผลกระทบต่อคำสั่งเรียก อย่างไรก็ตามสำหรับตัวแปรวัตถุมันใช้งานได้จริงมากเพราะตัวแปรวัตถุถูกส่งผ่านการอ้างอิงเมื่อผ่านไป ด้วยวิธีนี้การปรับเปลี่ยนตัวแปรวัตถุในวิธีการของคุณจะส่งผลกระทบต่อตัวแปรวัตถุในคำสั่งเรียก เมื่อคุณไม่จำเป็นต้องเปลี่ยนตัวแปรวัตถุเป็นพารามิเตอร์ในวิธีการอย่างชัดเจนการใช้ขั้นสุดท้ายสำหรับการประกาศจะป้องกันไม่ให้คุณแก้ไขโดยไม่ได้ตั้งใจและส่งผลกระทบต่อวิธีการโทร
1.6 เกี่ยวกับตัวแปรพารามิเตอร์ในคลาสด้านใน
นอกจากนี้เมื่อใช้ตัวแปรพารามิเตอร์ในวิธีการในคลาสด้านในตัวแปรพารามิเตอร์นี้จะต้องประกาศขั้นสุดท้ายก่อนที่จะสามารถใช้งานได้
ตัวอย่าง 6 inclass.java
คลาสสาธารณะรวม {void innerclass (สตริงสุดท้าย str) {คลาส iClass {iClass () {system.out.println (str); }} iClass IC = new iClass (); } โมฆะคงที่สาธารณะหลัก (สตริง [] args) {inclass inc = new inclass (); Inc.innerClass ("สวัสดี"); - 2. วิธีสุดท้าย
2.1 การใช้วิธีสุดท้าย
1) เพื่อให้แน่ใจว่าพฤติกรรมของฟังก์ชั่นบางอย่างยังคงไม่เปลี่ยนแปลงในระหว่างกระบวนการสืบทอดและไม่สามารถแทนที่ได้วิธีสุดท้ายสามารถใช้ได้
2) วิธีการส่วนตัวและแบบคงที่ทั้งหมดในชั้นเรียนถือเป็นที่สิ้นสุดตามธรรมชาติ
2.2 คำหลักสุดท้ายและส่วนตัว
วิธีการส่วนตัวทั้งหมดในชั้นเรียนได้รับการระบุโดยปริยายว่าเป็นที่สิ้นสุด เนื่องจากวิธีการส่วนตัวไม่สามารถใช้งานได้จึงไม่สามารถเขียนทับได้
"Override" จะปรากฏขึ้นหากวิธีการเป็นส่วนหนึ่งของอินเตอร์เฟสของคลาสฐาน นั่นคือวัตถุจะต้องสามารถเปลี่ยนเป็นประเภทดั้งเดิมและเรียกใช้วิธีเดียวกัน หากวิธีการเป็นส่วนตัวมันไม่ได้เป็นส่วนหนึ่งของอินเทอร์เฟซของคลาสฐาน มันเป็นเพียงรหัสบางส่วนที่ซ่อนอยู่ในชั้นเรียน แต่มีชื่อเดียวกัน อย่างไรก็ตามหากมีการสร้างวิธีการสาธารณะการป้องกันหรือการเข้าถึงแพ็คเกจในลักษณะเดียวกันในคลาสการส่งออกวิธีการจะไม่สร้างกรณี "มีชื่อเดียวกัน" ที่เกิดขึ้นในคลาสฐาน ณ จุดนี้คุณไม่ได้แทนที่วิธีการเพียงสร้างวิธีการใหม่ เนื่องจากวิธีการส่วนตัวไม่สามารถสัมผัสได้และสามารถซ่อนได้อย่างมีประสิทธิภาพจึงไม่จำเป็นต้องพิจารณาอย่างอื่นยกเว้นการดำรงอยู่ของโครงสร้างองค์กรของชั้นเรียนที่เป็นอยู่
3. ชั้นสุดท้าย
เมื่อคลาสถูกกำหนดให้เป็นขั้นสุดท้ายคลาสจะไม่สามารถสืบทอดได้ และเนื่องจากชั้นเรียนสุดท้ายห้ามมิให้มรดกวิธีการทั้งหมดในคลาสสุดท้ายจึงถูกระบุโดยปริยายว่าเป็นขั้นสุดท้ายเพราะไม่สามารถเขียนทับได้
สุดท้ายใช้ในชั้นเรียนหรือวิธีการเพื่อป้องกันการเชื่อมโยงระหว่างวิธีการจากการถูกทำลาย ตัวอย่างเช่นสมมติว่าการใช้วิธีการของ Class X ถือว่าวิธีการ M จะทำงานได้ในบางวิธี การประกาศ X หรือ M เป็นขั้นสุดท้ายจะป้องกันไม่ให้คลาสที่ได้รับจากการนิยามใหม่ M ด้วยวิธีนี้ทำให้ X ทำงานผิดปกติ แม้ว่ามันอาจจะดีกว่าที่จะใช้ X โดยไม่มีความสัมพันธ์ภายในเหล่านี้ แต่ก็ไม่สามารถทำได้เสมอไปและการใช้ขั้นสุดท้ายสามารถป้องกันการเปลี่ยนแปลงที่เข้ากันไม่ได้ในอนาคต
PS: ความแตกต่างระหว่างรอบชิงชนะเลิศในที่สุดและสรุป