close

28    存取權限控制

存取權限可區分為Class的存取權限及Class成員的存取權限。Class的成員包括欄位(field)與方法(method),欄位之基本資料型別及參考資料型別皆包含在內。存取權限有publicprotectedpackage access(沒有指定時)private四種,指定方法為置於定義之最前方。

 

[28-1 Class的存取權限]

Class的權限種類有publicpackage access(不指定時)兩種。權限修飾子指定public時,為其他class不論有無繼承關係、是否為同一package皆可來存取,也就是產生其物件。省略權限修飾子即為package access,也就是同一package內之其他class方可來存取,沒有設定package但在同一目錄內的class,視為同一package,即預設(default)package ,享有package access 之權限。classprivateprotected權限,不讓其他class來存取(產生物件)時,就必須將建構式宣告為private,不過卻可以靜態方法(static method)來產生物件。存取權限所指稱的Class皆是指編譯過後之.class檔而言,且是指被存取者,與存取者的權限無關。往下閱讀前可先參考「表28-1 Class存取權限」

 

[28-1-1 Classpublic權限]

[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:\access01Acc2801(建立物件)

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:\access01Acc2801(建立物件)

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 access01Acc2803(建立物件)

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 access01Acc2804(建立物件)

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成員含欄位(資料)及方法,其存取權限有publicprotecteddefault(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成員時 ,不可被不同packageclass來存取。

沒設定package時,同一目錄之class視為同一default package,不同目錄之class則需各自指名sourcepathclasspath

 

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權限之成員,可透過自身classstatic方法,被其他class存取。

arrow
arrow
    文章標籤
    存取權限
    全站熱搜

    祈泊 發表在 痞客邦 留言(0) 人氣()