1.Java有三種訪問許可權修飾符,分別為public、protected、private,還有一種為預設許可權修飾符的情況,記為default。其中,可以由public和default來修飾類;這四種修飾符都可以修飾成員變數和成員方法。每一種修飾符對應不同的訪問範圍,下麵以下圖為例詳細說明。 圖1 p ...
1.Java有三種訪問許可權修飾符,分別為public、protected、private,還有一種為預設許可權修飾符的情況,記為default。其中,可以由public和default來修飾類;這四種修飾符都可以修飾成員變數和成員方法。每一種修飾符對應不同的訪問範圍,下麵以下圖為例詳細說明。
圖1
- private只可以覆蓋圓1,即只有本類可以訪問;
- default可以覆蓋到圓3,即本類、同包子類、同包其他類都可以訪問,簡單說就是與本類同包的所有類都可以訪問;
- protected可以覆蓋到圓4,即本類、同包子類、同包其他類、其他包中的子類都可以訪問,簡單說就是與本類同包的類及其他包中的子類都可以訪問;
- public可以覆蓋到圓5,即本類、同包子類、同包其他類、其他包子類、其他包其他類都可以訪問,簡單說就是所有類都可以訪問;
註:在與父類不同包的子類中,如果通過子類對象訪問和調用父類中由protected修飾的變數和方法,確實可以;但如果通過父類的對象訪問和調用的話,則不可以訪問protected修飾的變數和方法,具體見下文的(6)和(7)。具體原因還未瞭解。
2.下麵以簡單的程式驗證上述結論。
前提:
- 包human中定義了類Person,Student,DustMan;其中,Student是Person的子類,DustMan不是Person的子類。
- 包teacher中定義了類Teacher,GateMan;其中,Teacher是Person的子類,GateMan不是Person的子類。
- Person中定義了四個成員變數和四個成員方法,分別以public,protected,預設,private修飾,詳見下麵代碼:
String name;
public String education; private String hobby; protected String residence; public void testModifierPublic() { System.out.println("Public"); } protected void testModifierProtected() { System.out.println("Protected"); } void testModifierDefault() { System.out.println("Default"); } private void testModifierPrivate() { System.out.println("Private"); }
(1),在Person類中定義Person類對象pOwn,分別訪問和調用這些成員變數和成員方法,詳見下麵的代碼:
public static void main(String[] args) { Person pOwn = new Person("xi",20,"female","bachelor","recite","NJ"); System.out.println("public education: " + pOwn.education); System.out.println("protected residence: " + pOwn.residence); System.out.println("default name: " + pOwn.name); System.out.println("private hobby: "+ pOwn.hobby); pOwn.testModifierPublic(); pOwn.testModifierProtected(); pOwn.testModifierDefault(); pOwn.testModifierPrivate(); }
輸出結果為:
public education: bachelor protected residence: NJ default name: xi private hobby: recite Public Protected Default Private
結果分析:Person類對象可以在本類中訪問和調用由public、protected、default、private修飾的成員變數和成員方法。
(2).在Student類中分別定義Student類對象sSamePackChild和Person類對象pSamePackChild,並分別訪問和調用這些成員變數和成員方法,詳見下麵的代碼:
public static void main(String[] args) { Student sSamePackChild = new Student("xi",20,"female","bachelor","recite","NJ"); Person pSamePackChild = new Person("xi",20,"female","bachelor","recite","NJ"); System.out.println("public education: " + sSamePackChild.education); System.out.println("protected residence: " + sSamePackChild.residence); System.out.println("default name: " + sSamePackChild.name); System.out.println("private hobby: "+ sSamePackChild.hobby); sSamePackChild.testModifierPublic(); sSamePackChild.testModifierProtected(); sSamePackChild.testModifierDefault(); sSamePackChild.testModifierPrivate(); System.out.println("public education: " + pSamePackChild.education); System.out.println("protected residence: " + pSamePackChild.residence); System.out.println("default name: " + pSamePackChild.name); System.out.println("private hobby: "+ pSamePackChild.hobby); pSamePackChild.testModifierPublic(); pSamePackChild.testModifierProtected(); pSamePackChild.testModifierDefault(); pSamePackChild.testModifierPrivate(); }
輸出結果為:
Exception in thread "main" java.lang.Error: Unresolved compilation problems: The field Person.hobby is not visible The method testModifierPrivate() from the type Person is not visible The field Person.hobby is not visible The method testModifierPrivate() from the type Person is not visible at human.Student.main(Student.java:108)
結果分析:出現編譯錯誤,提示private修飾的hobby和testModifierPrivate()不可見。
(3).根據(2)提示的錯誤,註釋掉相關的行,再次執行,詳見代碼:
public static void main(String[] args) { Student sSamePackChild = new Student("xi",20,"female","bachelor","recite","NJ"); Person pSamePackChild = new Person("xi",20,"female","bachelor","recite","NJ"); System.out.println("public education: " + sSamePackChild.education); System.out.println("protected residence: " + sSamePackChild.residence); System.out.println("default name: " + sSamePackChild.name); // System.out.println("private hobby: "+ sSamePackChild.hobby); sSamePackChild.testModifierPublic(); sSamePackChild.testModifierProtected(); sSamePackChild.testModifierDefault(); // sSamePackChild.testModifierPrivate(); System.out.println("public education: " + pSamePackChild.education); System.out.println("protected residence: " + pSamePackChild.residence); System.out.println("default name: " + pSamePackChild.name); // System.out.println("private hobby: "+ pSamePackChild.hobby); pSamePackChild.testModifierPublic(); pSamePackChild.testModifierProtected(); pSamePackChild.testModifierDefault(); // pSamePackChild.testModifierPrivate(); }
輸出結果為:
public education: bachelor protected residence: NJ default name: xi Public Protected Default public education: bachelor protected residence: NJ default name: xi Public Protected Default
結果分析:
註釋掉private修飾的行後,成功執行;
Person類對象可以在與父類同包的子類Student中訪問和調用由public、protected、default修飾的成員變數和成員方法,不能訪問由private修飾的變數和方法;
在子類中定義的Student類對象也擁有同樣的訪問許可權。
(4).在DustMan類中定義Person類對象pSamePackNonChild,分別訪問和調用這些成員變數和成員方法,詳見下麵的代碼:
package human; public class DustMan { public static void main(String[] args) { Person pSamePackNonChild = new Person("xi",20,"female","bachelor","recite","NJ"); System.out.println("public education: " + pSamePackNonChild.education); System.out.println("protected residence: " + pSamePackNonChild.residence); System.out.println("default name: " + pSamePackNonChild.name); System.out.println("private hobby: "+ pSamePackNonChild.hobby); pSamePackNonChild.testModifierPublic(); pSamePackNonChild.testModifierProtected(); pSamePackNonChild.testModifierDefault(); pSamePackNonChild.testModifierPrivate(); } }
輸出結果為:
Exception in thread "main" java.lang.Error: Unresolved compilation problems: The field Person.hobby is not visible The method testModifierPrivate() from the type Person is not visible at human.DustMan.main(DustMan.java:19)
結果分析:出現編譯錯誤,提示private修飾的hobby和testModifierPrivate()不可見。
(5).根據(4)提示的錯誤,註釋掉相關的行,再次執行,詳見代碼:
package human; public class DustMan { public static void main(String[] args) { Person pSamePackNonChild = new Person("xi",20,"female","bachelor","recite","NJ"); System.out.println("public education: " + pSamePackNonChild.education); System.out.println("protected residence: " + pSamePackNonChild.residence); System.out.println("default name: " + pSamePackNonChild.name); // System.out.println("private hobby: "+ pSamePackNonChild.hobby); pSamePackNonChild.testModifierPublic(); pSamePackNonChild.testModifierProtected(); pSamePackNonChild.testModifierDefault(); // pSamePackNonChild.testModifierPrivate(); } }
輸出結果為:
public education: bachelor protected residence: NJ default name: xi Public Protected Default
結果分析:
註釋掉private修飾的行後,成功執行;
Person類對象可以在與Person同包的非子類中訪問和調用由public、protected、default修飾的成員變數和成員方法,不能訪問由private修飾的變數和方法。
(6).在Teacher類中定義Teacher類對象tDiffPackChild和Person類對象pDiffPackChild,並分別訪問和調用這些成員變數和成員方法,詳見下麵的代碼:
package teacher; import human.Person; public class Teacher extends human.Person { String duty; public Teacher() { } public Teacher(String d) { super(); this.duty = d; } public Teacher(String n, int a, String g, String e, String h, String r) { super(n,a,g,e,h,r); } public static void main(String[] args) { Teacher tDiffPackChild = new Teacher("xi",20,"female","bachelor","recite","NJ"); Person pDiffPackChild = new Person("xi",20,"female","bachelor","recite","NJ"); System.out.println("public education: " + tDiffPackChild.education); System.out.println("protected residence: " + tDiffPackChild.residence); System.out.println("default name: " + tDiffPackChild.name); System.out.println("private hobby: "+ tDiffPackChild.hobby); tDiffPackChild.testModifierPublic(); tDiffPackChild.testModifierProtected(); tDiffPackChild.testModifierDefault(); tDiffPackChild.testModifierPrivate(); System.out.println("public education: " + pDiffPackChild.education); System.out.println("protected residence: " + pDiffPackChild.residence); System.out.println("default name: " + pDiffPackChild.name); System.out.println("private hobby: "+ pDiffPackChild.hobby); pDiffPackChild.testModifierPublic(); pDiffPackChild.testModifierProtected(); pDiffPackChild.testModifierDefault(); pDiffPackChild.testModifierPrivate(); } }
輸出結果為:
Exception in thread "main" java.lang.Error: Unresolved compilation problems: The field Person.name is not visible The field Person.hobby is not visible The method testModifierDefault() from the type Person is not visible The method testModifierPrivate() from the type Person is not visible The field Person.residence is not visible The field Person.name is not visible The field Person.hobby is not visible The method testModifierProtected() from the type Person is not visible The method testModifierDefault() from the type Person is not visible The method testModifierPrivate() from the type Person is not visible at teacher.Teacher.main(Teacher.java:39)
結果分析:
出現編譯錯誤,對於定義的Teacher類對象tDiffPackChild而言,對其的變數訪問和方法調用提示,default修飾的name和testModifierDefault()、private修飾的hobby和testModifierPrivate()不可見;
對於定義的Person類對象pDiffPackChild而言,對其的變數訪問和方法調用提示,protected修飾的residence和testModifierProtected()、default修飾的name和testModifierDefault()、private修飾的hobby和testModifierPrivate()不可見。
(7).根據(6)提示的錯誤,註釋掉相關的行,再次執行,詳見代碼:
package teacher; import human.Person; public class Teacher extends human.Person { String duty; public Teacher() { } public Teacher(String d) { super(); this.duty = d; } public Teacher(String n, int a, String g, String e, String h, String r) { super(n,a,g,e,h,r); } public static void main(String[] args) { Teacher tDiffPackChild = new Teacher("xi",20,"female","bachelor","recite","NJ"); Person pDiffPackChild = new Person("xi",20,"female","bachelor","recite","NJ"); System.out.println("public education: " + tDiffPackChild.education); System.out.println("protected residence: " + tDiffPackChild.residence); // System.out.println("default name: " + tDiffPackChild.name); // System.out.println("private hobby: "+ tDiffPackChild.hobby); tDiffPackChild.testModifierPublic(); tDiffPackChild.testModifierProtected(); // tDiffPackChild.testModifierDefault(); // tDiffPackChild.testModifierPrivate(); System.out.println("public education: " + pDiffPackChild.education); // System.out.println("protected residence: " + pDiffPackChild.residence); // System.out.println("default name: " + pDiffPackChild.name); // System.out.println("private hobby: "+ pDiffPackChild.hobby); pDiffPackChild.testModifierPublic(); // pDiffPackChild.testModifierProtected(); // pDiffPackChild.testModifierDefault(); // pDiffPackChild.testModifierPrivate(); } }
輸出結果為:
public education: bachelor protected residence: NJ Public Protected public education: bachelor Public
結果分析:
註釋掉相關的行後,成功執行;
如果在與Person不同包的子類Teacher中定義了Teacher類對象,則通過該對象可以訪問和調用Person中public和protected修飾的成員變數和成員方法,default、private修飾的成員變數和成員方法都不可以訪問或調用;
如果定義了Person類對象,則通過該對象只可以訪問和調用Person中public修飾的成員變數和成員方法,protected、default、private修飾的成員變數和成員方法都不可以訪問或調用。
疑問:不明白為什麼會有這樣的差異。
(8).在GateMan類中定義定義Person類對象pDiffPackNonChild,分別訪問和調用這些成員變數和成員方法,詳見下麵的代碼:
package teacher; import human.Person; public final class GateMan { int gateNumber; public GateMan() { } public GateMan(int g) { this.gateNumber = g; } public static void main(String[] args) { Person pDiffPackNonChild = new Person("xi",20,"female","bachelor","recite","NJ"); System.out.println("public education: " + pDiffPackNonChild.education); System.out.println("protected residence: " + pDiffPackNonChild.residence); System.out.println("default name: " + pDiffPackNonChild.name); System.out.println("private hobby: "+ pDiffPackNonChild.hobby); pDiffPackNonChild.testModifierPublic(); pDiffPackNonChild.testModifierProtected(); pDiffPackNonChild.testModifierDefault(); pDiffPackNonChild.testModifierPrivate(); } }
輸出結果為:
Exception in thread "main" java.lang.Error: Unresolved compilation problems: The field Person.residence is not visible The field Person.name is not visible The field Person.hobby is not visible The method testModifierProtected() from the type Person is not visible The method testModifierDefault() from the type Person is not visible The method testModifierPrivate() from the type Person is not visible at teacher.GateMan.main(GateMan.java:29)
結果分析:出現編譯錯誤,提示protected修飾的residence和testModifierProtected()、default修飾的name和testModifierDefault()、private修飾的hobby和testModifierPrivate()不可見。
(9).根據(8)提示的錯誤,註釋掉相關的行,再次執行,詳見代碼:
package teacher; import human.Person; public final class GateMan { int gateNumber; public GateMan() { } public GateMan(int g) { this.gateNumber = g; } public static void main(String[] args) { Person pDiffPackNonChild = new Person("xi",20,"female","bachelor","recite","NJ"); System.out.println("public education: " + pDiffPackNonChild.education); // System.out.println("protected residence: " + pDiffPackNonChild.residence); // System.out.println("default name: " + pDiffPackNonChild.name); // System.out.println("private hobby: "+ pDiffPackNonChild.hobby); pDiffPackNonChild.testModifierPublic(); // pDiffPackNonChild.testModifierProtected(); // pDiffPackNonChild.testModifierDefault(); // pDiffPackNonChild.testModifierPrivate(); } }
輸出結果為:
public education: bachelor Public
結果分析:
註釋掉protected、default、private修飾的行後,成功執行;
Person類對象可以在與Person不同包的非子類中訪問和調用由public修飾的成員變數和成員方法,不能訪問由protected、default、private修飾的變數和方法。
(10).把Person類定義為預設訪問許可權修飾的類,即class Person{,,,,}。在teacher包里的Teacher類和GateMan類都出現編譯錯誤,如下所示:
Exception in thread "main" java.lang.IllegalAccessError: class teacher.Teacher cannot access its superclass human.Person at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:763) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) at java.net.URLClassLoader.access$100(URLClassLoader.java:73) at java.net.URLClassLoader$1.run(URLClassLoader.java:368) at java.net.URLClassLoader$1.run(URLClassLoader.java:362) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:361) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:495)
結果分析:說明預設訪問許可權修飾符的類只能由本包中的類訪問,其他包中的類都不可以訪問。