ตัวปรับการเข้าถึง 'ป้องกัน' Java

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