1. ภาพรวม
ในภาษาการเขียนโปรแกรม Java ฟิลด์ตัวสร้างเมธอดและคลาสสามารถถูกทำเครื่องหมายด้วยตัวปรับการเข้าถึง ในบทช่วยสอนนี้เราจะดูการเข้าถึงที่มีการป้องกัน
2. คำหลักที่ได้รับการป้องกัน
แม้ว่าองค์ประกอบที่ประกาศว่าเป็นส่วนตัวจะสามารถเข้าถึงได้โดยคลาสที่ประกาศไว้เท่านั้น แต่คำหลักที่ได้รับการป้องกันจะอนุญาตให้เข้าถึงจากคลาสย่อยและสมาชิกในแพ็กเกจเดียวกัน
ด้วยการใช้คีย์เวิร์ดที่ได้รับการป้องกันเราจะทำการตัดสินใจเกี่ยวกับวิธีการและฟิลด์ที่ควรได้รับการพิจารณาภายในของแพ็กเกจหรือลำดับชั้นของคลาสและซึ่งจะเปิดเผยกับโค้ดภายนอก
3. การประกาศเขตข้อมูลวิธีการและตัวสร้างที่ได้รับการคุ้มครอง
ก่อนอื่นมาสร้างไฟล์คลาสชื่อFirstClassที่มีฟิลด์วิธีการและตัวสร้างที่ได้รับการป้องกัน :
public class FirstClass { protected String name; protected FirstClass(String name) { this.name = name; } protected String getName() { return name; } }
ด้วยตัวอย่างนี้โดยใช้การป้องกันคำหลักที่เราได้รับการเข้าถึงข้อมูลเหล่านี้จากการเรียนในแพคเกจเดียวกับFirstclassและย่อยชั้นเรียนของFirstclass
4. การเข้าถึงฟิลด์วิธีการและตัวสร้างที่ได้รับการป้องกัน
4.1 จากแพ็คเกจเดียวกัน
ตอนนี้เรามาดูกันว่าเราสามารถเข้าถึงฟิลด์ที่มีการป้องกันได้อย่างไรโดยการสร้างGenericClassใหม่ที่ประกาศในแพ็คเกจเดียวกับFirstClass :
public class GenericClass { public static void main(String[] args) { FirstClass first = new FirstClass("random name"); System.out.println("FirstClass name is " + first.getName()); first.name = "new name"; } }
เช่นนี้เรียกระดับอยู่ในแพคเกจเดียวกับFirstclass,มันได้รับอนุญาตให้ดูและโต้ตอบกับทุกการป้องกันเขตข้อมูลวิธีการและการก่อสร้าง
4.2. จากแพ็คเกจอื่น
ตอนนี้ลองโต้ตอบกับฟิลด์เหล่านี้จากคลาสที่ประกาศในแพ็คเกจอื่นจากFirstClass :
public class SecondGenericClass { public static void main(String[] args) { FirstClass first = new FirstClass("random name"); System.out.println("FirstClass name is "+ first.getName()); first.name = "new name"; } }
อย่างที่เราเห็นเราได้รับข้อผิดพลาดในการคอมไพล์ :
The constructor FirstClass(String) is not visible The method getName() from the type FirstClass is not visible The field FirstClass.name is not visible
นั่นคือสิ่งที่เราคาดหวังโดยใช้คำหลักที่มีการป้องกัน เนื่องจากSecondGenericClassไม่ได้อยู่ในแพ็คเกจเดียวกับFirstClassและไม่ได้อยู่ในคลาสย่อย
4.3 จากคลาสย่อย
ตอนนี้เรามาดูกันว่าจะเกิดอะไรขึ้นเมื่อเราประกาศคลาสที่ขยายFirstClassแต่ประกาศในแพ็คเกจอื่น :
public class SecondClass extends FirstClass { public SecondClass(String name) { super(name); System.out.println("SecondClass name is " + this.getName()); this.name = "new name"; } }
ตามที่คาดไว้เราสามารถเข้าถึงฟิลด์วิธีการและตัวสร้างที่มีการป้องกันทั้งหมด เพราะนี่คือSecondClassเป็นชั้นย่อยของFirstclass
5. ชั้นในที่ได้รับการป้องกัน
ในตัวอย่างก่อนหน้านี้เราเห็นฟิลด์วิธีการและตัวสร้างที่ได้รับการป้องกันในการดำเนินการ มีอีกกรณีหนึ่งที่เฉพาะเจาะจง - ชั้นในที่ได้รับการป้องกัน
มาสร้างคลาสภายในที่ว่างเปล่าภายในFirstClassของเรา:
package com.baeldung.core.modifiers; public class FirstClass { // ... protected static class InnerClass { } }
ในฐานะที่เราสามารถดูนี้เป็นระดับชั้นแบบคงที่และเพื่อให้สามารถสร้างขึ้นมาจากด้านนอกของตัวอย่างของFirstclass อย่างไรก็ตามในขณะที่มันจะได้รับการคุ้มครอง , เราสามารถยกตัวอย่างได้จากรหัสในแพคเกจเดียวกับ Firstclass
5.1 จากแพ็คเกจเดียวกัน
เพื่อทดสอบสิ่งนี้ให้แก้ไขGenericClassของเรา:
public class GenericClass { public static void main(String[] args) { // ... FirstClass.InnerClass innerClass = new FirstClass.InnerClass(); } }
ในฐานะที่เราสามารถดูเราสามารถยกตัวอย่างInnerClassโดยไม่มีปัญหาใด ๆ เพราะGenericClassอยู่ในแพคเกจเดียวกับFirstclass
5.2. จากแพ็คเกจอื่น
ลองยกตัวอย่างInnerClassจากเราSecondGenericClassที่ที่เราจำได้ว่าอยู่นอกFirstclass'แพคเกจ:
public class SecondGenericClass { public static void main(String[] args) { // ... FirstClass.InnerClass innerClass = new FirstClass.InnerClass(); } }
ตามที่คาดไว้เราได้รับข้อผิดพลาดในการคอมไพล์ :
The type FirstClass.InnerClass is not visible
5.3. จาก Sub-Class
ลองทำสิ่งเดียวกันจากSecondClassของเรา:
public class SecondClass extends FirstClass { public SecondClass(String name) { // ... FirstClass.InnerClass innerClass = new FirstClass.InnerClass(); } }
เราคาดหวังว่าจะสร้างอินสแตนซ์InnerClassของเราได้อย่างง่ายดาย อย่างไรก็ตามเราได้รับข้อผิดพลาดในการคอมไพล์ด้วยเช่นกัน:
The constructor FirstClass.InnerClass() is not visible
มาดูการประกาศInnerClassของเรา:
protected static class InnerClass { }
The main reason we are getting this error is that the default constructor of a protected class is implicitly protected. In addition, SecondClassis a sub-class of FirstClass but is not a sub-class of InnerClass. Finally, we also declaredSecondClass outside FirstClass' package.
For all these reasons, SecondClass can't access the protectedInnerClass constructor.
หากเราต้องการแก้ไขปัญหานี้และอนุญาตให้SecondClassของเราสร้างอินสแตนซ์อ็อบเจ็กต์InnerClass เราสามารถประกาศตัวสร้างสาธารณะได้อย่างชัดเจน :
protected static class InnerClass { public InnerClass() { } }
เมื่อทำเช่นนี้เราจะไม่ได้รับข้อผิดพลาดในการคอมไพล์อีกต่อไปและตอนนี้เราสามารถสร้างอินสแตนซ์InnerClassจากSecondClassได้แล้ว
6. บทสรุป
ในบทช่วยสอนฉบับย่อนี้เราได้พูดถึงตัวปรับการเข้าถึงที่มีการป้องกันใน Java ด้วยวิธีนี้เราสามารถมั่นใจได้ว่าจะเปิดเผยเฉพาะข้อมูลและวิธีการที่จำเป็นสำหรับคลาสย่อยและคลาสในแพ็คเกจเดียวกัน
เช่นเคยโค้ดตัวอย่างสามารถใช้ได้บน GitHub