Java學習筆記10---訪問權限修飾符如何控制成員變量、成員方法及類的訪問范圍


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)

結果分析:說明缺省訪問權限修飾符的類只能由本包中的類訪問,其他包中的類都不可以訪問。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM