28 存取權限控制
存取權限可區分為Class的存取權限及Class成員的存取權限。Class的成員包括欄位(field)與方法(method),欄位之基本資料型別及參考資料型別皆包含在內。存取權限有public、protected、package access(沒有指定時)及private四種,指定方法為置於定義之最前方。
[28-1 Class的存取權限]
Class的權限種類有public及package access(不指定時)兩種。權限修飾子指定public時,為其他class不論有無繼承關係、是否為同一package皆可來存取,也就是產生其物件。省略權限修飾子即為package access,也就是同一package內之其他class方可來存取,沒有設定package但在同一目錄內的class,視為同一package,即預設(default)的package ,享有package access 之權限。因class無private及protected權限,不讓其他class來存取(產生物件)時,就必須將建構式宣告為private,不過卻可以靜態方法(static method)來產生物件。存取權限所指稱的Class皆是指編譯過後之.class檔而言,且是指被存取者,與存取者的權限無關。往下閱讀前可先參考「表28-1 Class存取權限」
[28-1-1 Class的public權限]
[1.public且同一目錄例]
Acc2801編譯至C:\access01目錄中。
public class Acc2801{
String author = "神秀";
public void acc2801method(){
System.out.println("慧能師兄" + author + ":");
System.out.println("身似菩提樹,心似明鏡台,時時勤拂拭,勿使惹塵埃。");
}
}
編譯:
C:\access01>javac Acc2801.java
Exe2801編譯至C:\access01目錄中,存取同目錄C:\access01之Acc2801(建立物件)。
class Exe2801{
public static void main(String[] args){
Acc2801 a2801 = new Acc2801();
a2801.acc2801method();
}
}
編譯:
C:\access01>javac Exe2801.java
執行結果:
C:\access01>java Exe2801
慧能師兄神秀:
身似菩提樹,心似明鏡台,時時勤拂拭,勿使惹塵埃。
[2.public而不同目錄例]
Exe2803編譯至C:\access02中,存取不同目錄C:\access01之Acc2801(建立物件)。
class Exe2803{
public static void main(String[] args){
Acc2801 a2801 = new Acc2801();
a2801.acc2801method();
}
}
編譯:
C:\access02>javac -cp C:\access01 Exe2803.java
執行結果:
C:\access02>java -cp C:\access01;C:\access02 Exe2803
慧能師兄神秀:
身似菩提樹,心似明鏡台,時時勤拂拭,勿使惹塵埃。
[3.public且同一package例]
Acc2803編譯至package access01(即C:\access01目錄)中。
package access01; //設定package
public class Acc2803{
String author = "唐章懷太子李賢";
public void acc2803method(){
System.out.println(author + "〈黃台瓜辭〉");
System.out.println("「種瓜黃台下,瓜熟子離離。一摘使瓜好,再摘令瓜稀。三摘尚自可,摘絕抱蔓歸。」");
}
}
編譯:
C:\>javac access01\Acc2803.java
Exe2805編譯至package access01(即C:\access01目錄)中。
package access01; //設定package
//import access01.*; 引用目錄Acc2803所在package,因同目錄可省略
class Exe2805{
public static void main(String[] args){
Acc2803 a2803 = new Acc2803();
a2803.acc2803method();
}
}
編譯:
C:\>javac access01\Exe2805.java
執行結果:
C:\>java access01.Exe2805
唐章懷太子李賢〈黃台瓜辭〉
「種瓜黃台下,瓜熟子離離。一摘使瓜好,再摘令瓜稀。三摘尚自可,摘絕抱蔓歸。」
[4.public而不同package例]
Exe2807編譯至package access02中,存取package access01之Acc2803(建立物件)。
package access02;
import access01.*;
class Exe2807{
public static void main(String[] args){
Acc2803 a2803 = new Acc2803();
a2803.acc2803method();
}
}
編譯:
C:\>javac access02\Exe2807.java
執行結果:
C:\>java access02.Exe2807
唐章懷太子李賢〈黃台瓜辭〉
「種瓜黃台下,瓜熟子離離。一摘使瓜好,再摘令瓜稀。三摘尚自可,摘絕抱蔓歸。」
[28-1-2 Class的非public權限(沒有定義public)]
[1.非public而同一目錄例(視為同一package)]
Exe2802編譯至C:\access01目錄中,存取C:\access01目錄中之Acc2802(建立物件)。
class Acc2802{
String author = "慧能";
void acc2802method(){
System.out.println(author + ":");
System.out.println("菩提本無樹,明鏡亦非台,本來無一物,何處惹塵埃。");
}
}
編譯:
C:\access01>javac Acc2802.java
class Exe2802{
public static void main(String[] args){
Acc2802 a2802 = new Acc2802();
a2802.acc2802method();
}
}
編譯:
C:\access01>javac Exe2802.java
執行結果:
C:\access01>java Exe2802
慧能:
菩提本無樹,明鏡亦非台,本來無一物,何處惹塵埃。
[2.非public且不同目錄例(亦視為同一package)]
Exe2804編譯至C:\access02目錄中,存取C:\access01目錄中之Acc2802(建立物件)。
class Exe2804{
public static void main(String[] args){
Acc2802 a2802 = new Acc2802();
a2802.acc2802method();
}
}
編譯:
C:\access02>javac -cp C:\access01 Exe2804.java
執行結果:
C:\access02>java -cp C:\access01;C:\access02 Exe2804
慧能:
菩提本無樹,明鏡亦非台,本來無一物,何處惹塵埃。
沒有設定package時,則無論是否為同一目錄或是否為public類別,皆可被其他類別建立物件存取。
如有設定package時,且沒設為public,僅能為同一package或同一目錄內其他class來存取。
[3.非public而同一package例]
Acc2804編譯至package access01中。
package access01;
class Acc2804{
String author = "<<孟子>><告子上>";
void acc2804method(){
System.out.println(author);
System.out.println("魚,我所欲也;熊掌,亦我所欲也,二者不可得兼");
}
}
編譯:
C:\>javac access01\Acc2804.java
Exe2806編譯至同一package access01中。
package access01;
class Exe2806{
public static void main(String[] args){
Acc2804 a2804 = new Acc2804();
a2804.acc2804method();
}
}
編譯:
C:\>javac access01\Exe2806.java
執行結果:
C:\>java access01.Exe2806
<<孟子>><告子上>
魚,我所欲也;熊掌,亦我所欲也,二者不可得兼
[4.非public且非同一package例]
Exe2808編譯至package access02中,存取package access01之Acc2804(建立物件)。
package access02;
//import access01.*;
class Exe2808{
public static void main(String[] args){
access01.Acc2804 a2804 = new access01.Acc2804();
a2804.acc2804method();
}
}
編譯:
C:\>javac access02\Exe2808.java
access02\Exe2808.java:5: error: Acc2804 is not public in access01; cannot be accessed from outside package
access01.Acc2804 a2804 = new access01.Acc2804();
^
access02\Exe2808.java:5: error: Acc2804 is not public in access01; cannot be accessed from outside package
access01.Acc2804 a2804 = new access01.Acc2804();
^
2 errors
Class存取權限整理
被存取class 的權限 |
被存取class 的所在 |
去存取class 的權限 |
結果 |
說明 |
public |
同一目錄 |
不限 |
OK |
|
public |
不同目錄 |
不限 |
OK |
|
public |
同一package |
不限 |
OK |
|
public |
不同package |
不限 |
OK |
|
沒指定public |
同一目錄 |
不限 |
OK |
視為同default package |
沒指定 public |
不同目錄 |
不限 |
OK |
亦視為同default package |
沒指定public |
同一package |
不限 |
OK |
|
沒指定 public |
不同package |
不限 |
NO |
|
表28-1 Class存取權限
*這裡所指目錄皆為編譯過後之.class檔所在之目錄,非為原始碼所在之目錄。
*只有當沒指定public且不同package時不能被存取。沒定義package時,雖為不同目錄,視為同default package而可以存取。
[28-1-3 class的私有權限例]
Class並無private修飾子,但要如何防止別的Class來存取?可採取在建構式加上private修飾子的方式達成,也就是後述的Class內成員的存取權限。在此先說明private建構式。
建構式可參考前面章節的說明。沒有定義建構式者會自動產生一個沒有參數且無敘述式的建構式,稱為預設建構式。但如要定義為private者,則需自行定義建構式,即使一個沒有參數且無敘述式的建構式,也要加以定義,並加上private修飾子。具private屬性的建構式只有自身class可以存取,也就是建立自身物件。
<例>
Pri2811置入C:\access01中。
public class Pri2811{
private Pri2811( ){ }
static String author = "易經";
public static void main(String[] args){
Pri2811 p2811 = new Pri2811();
p2811.pri2811method();
}
public static void pri2811method(){
System.out.println(author + ":");
System.out.println("大人虎變。君子豹變。小人革面。");
}
public static void objgen(){ //static method
Pri2811 p2811s = new Pri2811();
p2811s.pri2811method();
}
}
執行結果:(具private建構式者,只有自身class可建立物件)
C:\access01>javac Pri2811.java
C:\access01>java Pri2811
易經:
大人虎變。君子豹變。小人革面。
<例>(他class無法建立具private建構式class物件)
Exe2811置入C:\access01中。
class Exe2811{
public static void main(String[] args){
Pri2811 a2811 = new Pri2811(); //無法建立具private建構式class物件
a2811. pri2811method();
}
}
執行結果:(編譯失敗)
C:\access01>javac Exe2811.java
Exe2811.java:3: error: Pri2811() has private access in Pri2811
Pri2811 a2811 = new Pri2811(); //無法建立具private建構式class物件
^
1 error
<例>(他class透過static method建立物件)
Exe2812置入C:\access01中。
class Exe2812{
public static void main(String[] args){
Pri2811. objgen(); //透過static method建立物件
}
}
執行結果:
C:\access01>javac Exe2812.java
C:\access01>java Exe2812
易經:
大人虎變。君子豹變。小人革面。
[28-2 Class成員的存取權限]
Class成員含欄位(資料)及方法,其存取權限有public、protected、default(package access)、private四種,需標示於成員定義的最前端。
欄位包含實值型別及參考型別。方法包含一般方法及建構式。
[28-2-1 Class成員public權限]
設定為public屬性的成員,可被所有其他位於任何目錄的類別來存取。
public屬性成員類別:
Macc280a置入C:\access01中。
public class Macc280a{
public String author;
public String title;
public void macc280amethod(){
System.out.println(author + "<" + title + ">" + ":");
System.out.println("錦瑟無端五十弦,一弦一柱思華年,莊生曉夢迷蝴蝶,望帝春心託杜鵑,滄海月明珠有淚,藍田日暖玉生煙,此情可待成追憶,只是當時已惘然。");
}
}
編譯:
C:\access01>javac Macc280a.java
存取類別:
Mexe280a置入C:\access02中。
class Mexe280a{
public static void main(String[] args){
Macc280a a280a = new Macc280a();
a280a.author = "李商隱";
a280a.title = "錦瑟";
a280a.macc280amethod();
}
}
編譯及執行:
C:\access02>javac -cp C:\access01 Mexe280a.java
C:\access02>java -cp C:\access01;C:\access02 Mexe280a
李商隱<錦瑟>:
錦瑟無端五十弦,一弦一柱思華年,莊生曉夢迷蝴蝶,望帝春心託杜鵑,滄海月明珠有淚,藍田日暖玉生煙,此情可待成追憶,只是當時已惘然。
[28-2-2 Class成員protected權限]
設定為protected屬性的成員僅可被所繼承的類別來存取。
protected屬性成員類別:
Macc280b置入C:\access01中。
public class Macc280b {
protected String author;
protected String title;
protected void macc280bmethod(){
System.out.println(author + "<" + title + ">" + ":");
System.out.println("錦瑟無端五十弦,一弦一柱思華年,莊生曉夢迷蝴蝶,望帝春心託杜鵑,滄海月明珠有淚,藍田日暖玉生煙,此情可待成追憶,只是當時已惘然。");
}
}
編譯:
C:\access01>javac Macc280b.java
繼承例:
Macc280c置入C:\access02中。
public class Macc280c extends Macc280b {
public static void main(String[] args){
Macc280b b280b = new Macc280b();
b280b.author = "李商隱";
b280b.title = "錦瑟";
b280b.macc280bmethod();
}
}
編譯及執行:
C:\access02>javac -cp C:\access01 Macc280c.java
C:\access02>java -cp C:\access01;C:\access02 Macc280c
李商隱<錦瑟>:
錦瑟無端五十弦,一弦一柱思華年,莊生曉夢迷蝴蝶,望帝春心託杜鵑,滄海月明珠有淚,藍田日暖玉生煙,此情可待成追憶,只是當時已惘然。
[28-2-3 Class成員package access權限]
省略修飾子(即為package)的成員僅可被同package的類別來存取。
Macc280e置於package access01中。
package access01;
public class Macc280e {
String author;
String title;
void macc280emethod(){
System.out.println(author + "<" + title + ">" + ":");
System.out.println("錦瑟無端五十弦,一弦一柱思華年,莊生曉夢迷蝴蝶,望帝春心託杜鵑,滄海月明珠有淚,藍田日暖玉生煙,此情可待成追憶,只是當時已惘然。");
}
}
編譯:
C:\>javac access01\Macc280e.java
Mexe280e置於package access01中。
package access01;
public class Mexe280e {
public static void main(String[] args){
Macc280e e280e = new Macc280e ();
e280e.author = "李商隱";
e280e.title = "錦瑟";
e280e.macc280emethod();
}
}
執行結果:
C:\>javac access01\Mexe280e.java
C:\>java access01.Mexe280e
李商隱<錦瑟>:
錦瑟無端五十弦,一弦一柱思華年,莊生曉夢迷蝴蝶,望帝春心託杜鵑,滄海月明珠有淚,藍田日暖玉生煙,此情可待成追憶,只是當時已惘然。
設定為Package存取權限之class成員時 ,不可被不同package之class來存取。
沒設定package時,同一目錄之class視為同一default package,不同目錄之class則需各自指名sourcepath及classpath。
Mexe28f置於package access02中。
package access02;
public class Mexe280f {
public static void main(String[] args){
Macc280e f280f = new Macc280e ();
f280f.author = "李商隱";
f280f.title = "錦瑟";
f280f.macc280emethod();
}
}
執行結果:
C:\>javac access02\Mexe280f.java
C:\>java access02.Mexe280f
[28-2-4 Class成員private權限]
設定為private屬性的成員僅可被自身類別來存取。
自身存取:
public class Macc280f{
private Macc280f(){}
private static String author;
private static String title;
public static void main(String[] args){
author = "曹操";
title = "龜雖壽";
System.out.println(author + "<" + title + ">" + ":");
System.out.println("老驥伏櫪,志在千里;烈士暮年,壯心不已。");
}
}
執行結果:
C:\access01>javac Macc280f.java
C:\access01>java Macc280f
曹操<龜雖壽>:
老驥伏櫪,志在千里;烈士暮年,壯心不已。
非自身存取:
設定private建構式其他class即無法產生該物件,無論成員的權限設定為何,也無法去存取。如果建構式不是private,雖可建立物件,卻也無法存取其他private成員。
public class Macc280g{
private Macc280g(){} //如果為非private,亦無法存取下述兩個成員
private String author;
private String title;
public void macc280gmethod(){
author = "曹操";
title = "龜雖壽";
System.out.println(author + "<" + title + ">" + ":");
System.out.println("老驥伏櫪,志在千里;烈士暮年,壯心不已。");
}
}
編譯:
C:\access01>javac Macc280g.java
public class Mexe280g{
public static void main(String[] args){
Macc280g g280g = new Macc280g ();
g280g.author = "曹操";
g280g.title = "龜雖壽";
g280g.macc280gmethod();
}
}
編譯及執行:
C:\access01>javac Mexe280g.java
Mexe280g.java:3: error: Macc280g() has private access in Macc280g
Macc280g g280g = new Macc280g ();
^
Mexe280g.java:4: error: author has private access in Macc280g
g280g.author = "曹操";
^
Mexe280g.java:5: error: title has private access in Macc280g
g280g.title = "龜雖壽";
^
3 errors
建構式雖為private,也可透過static方法建立物件。
public class Macc280h{
private Macc280h(){}
String author;
String title;
void macc280hmethod(){
author = "曹操";
title = "龜雖壽";
System.out.println(author + "<" + title + ">" + ":");
System.out.println("老驥伏櫪,志在千里;烈士暮年,壯心不已。");
}
public static Macc280h objgen(){
return new Macc280h();
}
}
編譯:
C:\access01>javac Macc280h.java
public class Mexe280h{
public static void main(String[] args){
Macc280h h280h = Macc280h.objgen();
h280h.macc280hmethod();
}
}
編譯及執行:
C:\access01>javac Mexe280h.java
C:\access01>java Mexe280h
曹操<龜雖壽>:
老驥伏櫪,志在千里;烈士暮年,壯心不已。
資料欄位雖定為private,也可透過static方法設定及取得內容。
public class Macc280i{
private String author = "曹操";
private String title;
public static String itemget(){
return author;
}
public static void itemset(String tit){
title = tit;
}
public static void print01(){
System.out.println(author + "<" + title + ">" + ":");
System.out.println("老驥伏櫪,志在千里;烈士暮年,壯心不已。");
}
}
編譯:
C:\access01>javac Macc280i.java
public class Mexe280i{
public static void main(String[] args){
String aut;
Macc280i i280i = new Macc280i();
aut = i280i.itemget();
System.out.println("author = " + aut);
i280i.itemset("龜雖壽");
i280i.print01();
}
}
編譯及執行:
C:\access01>javac Mexe280i.java
C:\access01>java Mexe280i
author = 曹操
曹操<龜雖壽>:
老驥伏櫪,志在千里;烈士暮年,壯心不已。
Class成員權限
被存取的 class 成員權限 |
去存取的class可否存取 |
||||
被存取的、去存取的class編譯後.class檔所在位置 |
|||||
package |
非package |
||||
同 package |
不同 package |
同 directory |
不同 directory |
||
public |
可 |
可 |
可 |
可 |
|
protected |
繼承 |
可 |
可 |
可 |
可 |
非繼承 |
可 |
不可 |
可 |
可 |
|
package |
可 |
不可 |
可 |
可 |
|
private |
不可 |
不可 |
不可 |
不可 |
表28-2 Class成員權限
成員無論權限為何,classc自身皆可存取。
沒有設定package成員權限時,class無論身處任何directory,皆視為同一default directory。
protected成員權限亦具有package成員權限,如上表protected之非繼承部分,權限如同package。
private權限之成員,可透過自身class之static方法,被其他class存取。
留言列表