ฉันเพิ่งเริ่มอ่านหนังสือ Java และสงสัยว่า ตัวระบุการเข้าถึงใดเป็นค่าเริ่มต้นหากไม่มีการระบุ
ฉันเพิ่งเริ่มอ่านหนังสือ Java และสงสัยว่า ตัวระบุการเข้าถึงใดเป็นค่าเริ่มต้นหากไม่มีการระบุ
คำตอบ:
การมองเห็นเริ่มต้นเรียกว่า "package-private" (แม้ว่าคุณจะไม่สามารถใช้สิ่งนี้ได้อย่างชัดเจน) ซึ่งหมายความว่าจะสามารถเข้าถึงฟิลด์นี้ได้จากภายในแพ็กเกจเดียวกันกับคลาสที่เป็นสมาชิก
ดังที่ mdma ชี้ให้เห็นมันไม่เป็นความจริงสำหรับสมาชิกอินเทอร์เฟซซึ่งค่าเริ่มต้นคือ "สาธารณะ"
ตัวระบุเริ่มต้นขึ้นอยู่กับบริบท
สำหรับคลาสและการประกาศอินเทอร์เฟซค่าดีฟอลต์คือแพ็กเกจส่วนตัว สิ่งนี้อยู่ระหว่างการป้องกันและไพรเวตอนุญาตให้เฉพาะคลาสในการเข้าถึงแพ็กเกจเดียวกัน (การป้องกันเป็นเช่นนี้ แต่ยังอนุญาตให้เข้าถึงคลาสย่อยภายนอกแพ็คเกจด้วย)
class MyClass // package private
{
int field; // package private field
void calc() { // package private method
}
}
สำหรับสมาชิกอินเทอร์เฟซ (ฟิลด์และวิธีการ) การเข้าถึงเริ่มต้นจะเป็นแบบสาธารณะ แต่โปรดทราบว่าการประกาศอินเทอร์เฟซนั้นมีค่าเริ่มต้นเป็นแพ็กเกจส่วนตัว
interface MyInterface // package private
{
int field1; // static final public
void method1(); // public abstract
}
ถ้าเรามีคำประกาศ
public interface MyInterface2 extends MyInterface
{
}
จากนั้นคลาสที่ใช้ MyInterface2 จะเห็น field1 และ method1 จาก super interface เนื่องจากเป็นแบบสาธารณะแม้ว่าจะไม่เห็นการประกาศ MyInterface ก็ตาม
/* pp */
) เป็นเพียงชื่อที่สะดวกสำหรับการเข้าถึงเริ่มต้น ไม่ใช่ชื่อ JLS
หากไม่มีการระบุตัวระบุการเข้าถึงเป็นการเข้าถึงระดับแพ็กเกจ (ไม่มีตัวระบุที่ชัดเจนสำหรับสิ่งนี้) สำหรับคลาสและสมาชิกคลาส วิธีการเชื่อมต่อเป็นแบบสาธารณะโดยปริยาย
การเปิดเผยเริ่มต้น (ไม่มีคีย์เวิร์ด) คือ แพ็กเกจซึ่งหมายความว่าจะสามารถใช้ได้กับทุกคลาสที่อยู่ในแพ็กเกจเดียวกัน
ข้อสังเกตที่น่าสนใจคือการป้องกันไม่ได้ จำกัด การมองเห็นเฉพาะคลาสย่อย แต่ยังรวมถึงคลาสอื่น ๆ ในแพ็คเกจเดียวกันด้วย
มันขึ้นอยู่กับว่าสิ่งนั้นคืออะไร
ประเภทระดับบนสุด (นั่นคือคลาส enums อินเทอร์เฟซและประเภทคำอธิบายประกอบที่ไม่ได้ประกาศไว้ในประเภทอื่น) เป็นแพ็กเกจส่วนตัวตามค่าเริ่มต้น ( JLS §6.6.1 )
ในคลาสสมาชิกทั้งหมด (ซึ่งหมายถึงเขตข้อมูลวิธีการและการประกาศชนิดที่ซ้อนกัน) และตัวสร้างจะเป็นแพ็กเกจส่วนตัวตามค่าเริ่มต้น ( JLS §6.6.1 )
ใน enums ตัวสร้างเป็นแบบส่วนตัวโดยค่าเริ่มต้น อันที่จริงผู้ควบคุม enum ต้องเป็นแบบส่วนตัวและเป็นข้อผิดพลาดในการระบุว่าเป็นสาธารณะหรือได้รับการคุ้มครอง ค่าคงที่ของ Enum เป็นแบบสาธารณะเสมอและไม่อนุญาตให้ใช้ตัวระบุการเข้าถึงใด ๆ สมาชิกอื่น ๆ ของ enums เป็นแพ็กเกจส่วนตัวตามค่าเริ่มต้น ( JLS §8.9 )
ในอินเทอร์เฟซและประเภทคำอธิบายประกอบสมาชิกทั้งหมด (อีกครั้งนั่นหมายถึงฟิลด์วิธีการและการประกาศประเภทที่ซ้อนกัน) เป็นสาธารณะโดยค่าเริ่มต้น อันที่จริงสมาชิกของอินเทอร์เฟซและประเภทคำอธิบายประกอบต้องเป็นสาธารณะและเป็นข้อผิดพลาดในการระบุว่าเป็นส่วนตัวหรือได้รับการป้องกัน ( JLS §9.3ถึง 9.5 )
คลาสโลคัลเป็นชื่อคลาสที่ประกาศภายในเมธอดตัวสร้างหรือบล็อกตัวเริ่มต้น พวกเขาถูกกำหนดขอบเขตไว้ที่{
.. }
บล็อกที่มีการประกาศและไม่อนุญาตตัวระบุการเข้าถึงใด ๆ ( JLS §14.3 ) การใช้การสะท้อนคุณสามารถสร้างอินสแตนซ์คลาสโลคัลจากที่อื่นได้และเป็นแบบแพ็กเกจส่วนตัวแม้ว่าฉันจะไม่แน่ใจว่ารายละเอียดนั้นอยู่ใน JLS หรือไม่
คลาสแบบไม่ระบุชื่อคือคลาสแบบกำหนดเองที่สร้างขึ้นโดยnew
ระบุเนื้อหาคลาสโดยตรงในนิพจน์ ( JLS §15.9.5 ) ไวยากรณ์ของพวกเขาไม่อนุญาตตัวระบุการเข้าถึงใด ๆ การใช้การไตร่ตรองคุณสามารถสร้างอินสแตนซ์คลาสที่ไม่ระบุตัวตนจากที่อื่นได้และทั้งสองและตัวสร้างที่สร้างขึ้นนั้นเป็นแพ็คเกจส่วนตัวแม้ว่าฉันจะไม่แน่ใจว่ารายละเอียดนั้นอยู่ใน JLS หรือไม่
อินสแตนซ์และบล็อกตัวเริ่มต้นแบบคงที่ไม่มีตัวระบุการเข้าถึงที่ระดับภาษา ( JLS §8.6 & 8.7 ) แต่บล็อกตัวเริ่มต้นแบบคงที่ถูกนำไปใช้เป็นวิธีการที่ชื่อ<clinit>
( JVMS §2.9 ) ดังนั้นเมธอดจะต้องมีตัวระบุการเข้าถึงภายใน ผมตรวจสอบการเรียนการรวบรวมโดย javac และคอมไพเลอร์ของ Eclipse ใช้ Hex Editor และพบว่าทั้งสองวิธีการสร้างเป็นแพคเกจและเอกชน อย่างไรก็ตามคุณไม่สามารถเรียก<clinit>()
ภายในภาษาได้เนื่องจาก<
และ>
อักขระไม่ถูกต้องในชื่อเมธอดและเมธอดการสะท้อนถูกเดินสายเพื่อปฏิเสธการมีอยู่ของมันดังนั้นตัวระบุการเข้าถึงที่มีประสิทธิภาพจึงไม่สามารถเข้าถึงได้ VM เท่านั้นที่สามารถเรียกเมธอดได้ในระหว่างการเริ่มต้นคลาสบล็อกตัวเริ่มต้นอินสแตนซ์ไม่ได้รวบรวมเป็นวิธีการแยกต่างหาก รหัสของพวกเขาจะถูกคัดลอกไปยังตัวสร้างแต่ละตัวดังนั้นจึงไม่สามารถเข้าถึงทีละตัวได้แม้จะเป็นการสะท้อน
defaultคือคีย์เวิร์ดที่ใช้เป็นตัวแก้ไขการเข้าถึงสำหรับเมธอดและตัวแปร
การใช้ตัวแก้ไขการเข้าถึงนี้จะทำให้คลาสตัวแปรวิธีการหรือตัวสร้างของคุณสามารถเข้าถึงได้จากคลาสหรือแพ็กเกจของตัวเองมันจะถูกตั้งค่าด้วยหากไม่มีตัวปรับการเข้าถึงอยู่
Access Levels
Modifier Class Package Subclass EveryWhere
public Y Y Y Y
protected Y Y Y N
default Y Y N N
private Y N N N
หากคุณใช้ค่าเริ่มต้นในอินเทอร์เฟซคุณจะสามารถใช้วิธีการดังตัวอย่างนี้ได้
public interface Computer {
default void Start() {
throw new UnsupportedOperationException("Error");
}
}
อย่างไรก็ตามมันจะใช้งานได้จากเวอร์ชัน 8 Java เท่านั้น
ดูที่นี่สำหรับรายละเอียดเพิ่มเติม ค่าเริ่มต้นคือไม่มีส่วนบุคคล / สาธารณะ / ป้องกัน แต่เป็นข้อกำหนดการเข้าถึงที่แตกต่างกันโดยสิ้นเชิง ไม่ได้ใช้กันอย่างแพร่หลายและฉันต้องการเจาะจงมากขึ้นในคำจำกัดความการเข้าถึงของฉัน
ตัวระบุการเข้าถึงเริ่มต้นคือแพ็กเกจชั้นเรียนสามารถเข้าถึงสมาชิกของคลาสอื่น ๆ ในแพ็กเกจเดียวกัน แต่ภายนอกแพ็กเกจจะปรากฏเป็นส่วนตัว
นี่คือคำพูดเกี่ยวกับการมองเห็นระดับแพ็กเกจจากบทสัมภาษณ์ของ James Gosling ผู้สร้าง Java:
Bill Venners : Java มีระดับการเข้าถึงสี่ระดับ ค่าเริ่มต้นคือแพ็คเกจ ฉันสงสัยมาตลอดว่าการทำให้การเข้าถึงแพ็กเกจเป็นค่าเริ่มต้นนั้นสะดวกหรือไม่เพราะคำหลักสามคำที่ผู้คนจาก C ++ รู้อยู่แล้วนั้นเป็นแบบส่วนตัวได้รับการป้องกันและสาธารณะ หรือหากคุณมีเหตุผลบางอย่างที่คุณคิดว่าการเข้าถึงแพ็กเกจควรเป็นค่าเริ่มต้น
เจมส์กอสลิง : โดยทั่วไปแล้วแพคเกจคือชุดของสิ่งต่างๆที่เขียนร่วมกัน โดยทั่วไปฉันสามารถทำหนึ่งในสองสิ่งได้ อย่างหนึ่งคือบังคับให้คุณใส่คำหลักที่ให้โดเมนแก่คุณเสมอ หรือฉันอาจมีค่าเริ่มต้น คำถามคืออะไรทำให้ค่าเริ่มต้นที่สมเหตุสมผล? และฉันมักจะไปหาสิ่งที่อันตรายน้อยที่สุด
สาธารณะคงเป็นเรื่องแย่มากที่จะตั้งค่าเริ่มต้น ส่วนตัวอาจเป็นเรื่องไม่ดีที่จะทำให้ผิดนัดถ้าเพียงเพราะคนไม่ได้เขียนวิธีการส่วนตัวบ่อยๆ และสิ่งเดียวกันกับการป้องกัน และจากการดูโค้ดจำนวนมากที่ฉันมีฉันตัดสินใจว่าสิ่งที่พบบ่อยที่สุดที่ปลอดภัยพอสมควรอยู่ในแพ็คเกจ และ C ++ ไม่มีคีย์เวิร์ดสำหรับสิ่งนั้นเนื่องจากไม่มีแนวคิดเกี่ยวกับแพ็คเกจ
แต่ฉันชอบมันมากกว่าความคิดเรื่องเพื่อนเพราะกับเพื่อนคุณต้องระบุว่าเพื่อนของคุณเป็นใครดังนั้นหากคุณเพิ่มคลาสใหม่ลงในแพ็กเกจโดยทั่วไปแล้วคุณจะต้องไปที่ทั้งหมด เรียนในแพ็คเกจนั้นและอัปเดตเพื่อนของพวกเขาซึ่งฉันมักจะพบว่าปวดก้นอย่างสมบูรณ์
แต่รายชื่อเพื่อนเองทำให้เกิดปัญหาการกำหนดเวอร์ชัน ดังนั้นจึงมีแนวคิดเกี่ยวกับชนชั้นที่เป็นมิตรนี้ และสิ่งที่ดีที่ฉันทำให้เป็นค่าเริ่มต้น - ฉันจะแก้ปัญหาแล้วคำหลักควรเป็นอย่างไร
ในขณะที่มีคำหลักที่เป็นมิตรจริงๆ แต่เนื่องจากตัวอื่น ๆ ทั้งหมดขึ้นต้นด้วย "P" จึงเป็น "เพื่อน" พร้อมกับ "PH" แต่นั่นเป็นเพียงแค่วันเดียวเท่านั้น
อัปเดตการใช้คีย์เวิร์ดJava 8default
: ดังที่คนอื่น ๆ สังเกตเห็นการมองเห็นเริ่มต้น (ไม่มีคีย์เวิร์ด)
คุณสามารถเข้าถึงฟิลด์นี้ได้จากภายในแพ็กเกจเดียวกันกับคลาสนั้น ๆ
เพื่อไม่ให้สับสนกับคุณลักษณะใหม่ของJava 8 ( วิธีการเริ่มต้น ) ที่อนุญาตให้อินเทอร์เฟซจัดเตรียมการนำไปใช้งานเมื่อมีป้ายกำกับด้วยdefault
คีย์เวิร์ด
มีตัวแก้ไขการเข้าถึงที่เรียกว่า "ค่าเริ่มต้น" ใน JAVA ซึ่งอนุญาตให้สร้างอินสแตนซ์โดยตรงของเอนทิตีนั้นภายในแพ็คเกจนั้นเท่านั้น
นี่คือลิงค์ที่มีประโยชน์:
ก่อนอื่นให้ฉันพูดสิ่งหนึ่งที่ไม่มีคำว่า "Access specifier" ใน java เราควรเรียกทุกอย่างว่า "Modifiers" ดังที่เราทราบว่าขั้นสุดท้ายคงที่ซิงโครไนซ์ระเหย .... ถูกเรียกว่าเป็นโมดิฟายเออร์แม้แต่ Public, private, protected, default, abstract ก็ควรเรียกว่าเป็นโมดิฟายเออร์ ค่าดีฟอลต์คือโมดิฟายเออร์ที่ไม่มีการดำรงอยู่ทางกายภาพ แต่ไม่มีการวางโมดิฟายเออร์จึงควรถือว่าเป็นโมดิฟายเออร์เริ่มต้น
เพื่อให้เหตุผลนี้ใช้ตัวอย่างเดียว:
public class Simple{
public static void main(String args[]){
System.out.println("Hello Java");
}
}
ผลลัพธ์จะเป็น: Hello Java
ตอนนี้เปลี่ยน public เป็น private และดูข้อผิดพลาดของคอมไพเลอร์ที่คุณได้รับ: มันแจ้งว่า "Modifier private is not allowed here" ข้อสรุปคือบางคนอาจผิดหรือบทช่วยสอนบางอย่างอาจผิด แต่คอมไพเลอร์ไม่สามารถผิดได้ ดังนั้นเราจึงสามารถพูดได้ว่าไม่มีตัวระบุการเข้าถึงคำศัพท์ใน java ทุกอย่างเป็นตัวปรับเปลี่ยน