1. 程式人生 > >java程式設計思想 第 6 章 訪問許可權控制

java程式設計思想 第 6 章 訪問許可權控制

更新類庫時為了讓開發人員知道哪些類是被其它類引用的,不能被修改而引人了訪問許可權控制。

public > protect >(預設) > private

一、包:庫單元

包內包含一組類、它們在單一的名稱空間下被組織到了一起:

java.utils.ArrayList使用,使用全限定名:

//: access/FullQualification.java

public class FullQualification {
  public static void main(String[] args) {
    java.util.ArrayList list = new
java.util.ArrayList(); } } ///:~

使用import匯入

//: access/SingleImport.java
import java.util.ArrayList;

public class SingleImport {
  public static void main(String[] args) {
    ArrayList list = new java.util.ArrayList();
  }
} ///:~

同一包下全匯入

import java.util.*;

未指明包名為,位於預設包下。

一個*.java 檔案為一個編譯單元。該編譯單元有且只有一個public類且與*.java

檔名相同 和多個非public 類。編譯成功後生成以類為單位的多個*.class檔案

1.1 程式碼組織

在檔案中第一行為類指定包名(包名

必須小寫):

package access;

建立一個MyClass.java 檔案,有且只有一個同名的public 類。

//: access/mypackage/MyClass.java
package access.mypackage;

public class MyClass {
  // ...
} ///:~

MyClass類受access.mypackage包保護,如果MyClass類和該包下其它公共類,使用全限定名或者import關鍵字匯入
全限定名:

//: access/QualifiedMyClass.java

public class QualifiedMyClass {
  public static void main(String[] args) {
    access.mypackage.MyClass m =
      new access.mypackage.MyClass();
  }
} ///:~

import匯入:

//: access/ImportedMyClass.java
import access.mypackage.*;

public class ImportedMyClass {
  public static void main(String[] args) {
    MyClass m = new MyClass();
  }
} ///:~

package 和 import 將單一的全域性名稱空間割開,防止出現名稱衝突。

1.2 建立獨一無二的包名

建立一個名為simple的類庫

包名:net.mindview.simple

該名稱下才兩個字檔案

Vector.java

//: net/mindview/simple/Vector.java
// Creating a package.
package net.mindview.simple;

public class Vector {
  public Vector() {
    System.out.println("net.mindview.simple.Vector");
  }
} ///:~

List.java

//: net/mindview/simple/List.java
// Creating a package.
package net.mindview.simple;

public class List {
  public List() {
    System.out.println("net.mindview.simple.List");
  }
} ///:~

兩個檔案都位於K:\研二\Java\thindinjava\code1\net\mindview\simple路徑下

而向ClassPath添加了K:\研二\Java\thindinjava\code1路徑。

LibTest.java 檔案可以位於任何目錄:

//: access/LibTest.java
// Uses the library.
import net.mindview.simple.*;

public class LibTest {
  public static void main(String[] args) {
    Vector v = new Vector();
    List l = new List();
  }
} /* Output:
net.mindview.simple.Vector
net.mindview.simple.List
*///:~

編譯器編譯該檔案碰到import語句時,會去ClassPath中的目錄中查詢子目錄\net\mindview\simple,然後編譯出相應的類檔案。

練習二:衝突

// access/Collision.java
// TIJ4 Chapter Access, Exercise 2, page 217
/* Take the code fragments in this section and turn them into a program and 
* verify that collisions do occur.
*/
import net.mindview.simple.*;
import java.util.*;

public class Collision {
    public static void main(String[] args) {
        // Vector v = new Vector(); // ambiquous collision
        net.mindview.simple.Vector v1 = new net.mindview.simple.Vector();
        java.util.Vector v2 = new java.util.Vector();
    }
}

第一行取消註釋時提示:

K:\研二\Java\thindinjava\code2\Access>javac Collision.java
Collision.java:11: 錯誤: 對Vector的引用不明確
                 Vector v = new Vector(); // ambiquous collision
                 ^
  java.util 中的類 java.util.Vector 和 net.mindview.simple 中的類 net.mindview.simple.Vector 都匹配
Collision.java:11: 錯誤: 對Vector的引用不明確
                 Vector v = new Vector(); // ambiquous collision
                                ^
  java.util 中的類 java.util.Vector 和 net.mindview.simple 中的類 net.mindview.simple.Vector 都匹配
2 個錯誤

1.3 定製工具庫

建立一個名為Print.java工具庫

//: net/mindview/util/Print.java
// Print methods that can be used without
// qualifiers, using Java SE5 static imports:
package net.mindview.util;
import java.io.*;

public class Print {
  // Print with a newline:
  public static void print(Object obj) {
    System.out.println(obj);
  }
  // Print a newline by itself:
  public static void print() {
    System.out.println();
  }
  // Print with no line break:
  public static void printnb(Object obj) {
    System.out.print(obj);
  }
  // The new Java SE5 printf() (from C):
  public static PrintStream
  printf(String format, Object... args) {
    return System.out.printf(format, args);
  }
} ///:~

編譯完成後,使用import static靜態匯入該類,可以使用該類的靜態方法

//: access/PrintTest.java
// Uses the static printing methods in Print.java.
import static net.mindview.util.Print.*;

public class PrintTest {
  public static void main(String[] args) {
    print("Available from now on!");
    print(100);
    print(100L);
    print(3.14159);
  }
} /* Output:
Available from now on!
100
100
3.14159
*///:~

Rage.java工具類

//: net/mindview/util/Range.java
// Array creation methods that can be used without
// qualifiers, using Java SE5 static imports:
package net.mindview.util;

public class Range {
  // Produce a sequence [0..n)
  public static int[] range(int n) {
    int[] result = new int[n];
    for(int i = 0; i < n; i++)
      result[i] = i;
    return result;
  }
  // Produce a sequence [start..end)
  public static int[] range(int start, int end) {
    int sz = end - start;
    int[] result = new int[sz];
    for(int i = 0; i < sz; i++)
      result[i] = start + i;
    return result;
  }
  // Produce a sequence [start..end) incrementing by step
  public static int[] range(int start, int end, int step) {
    int sz = (end - start)/step;
    int[] result = new int[sz];
    for(int i = 0; i < sz; i++)
      result[i] = start + (i * step);
    return result;
  }
} ///:~

1.4

練習三

// access/debug/Debug.java
// TIJ4 Chapter Access, Exercise 3, page 220
/* Create two packages: debug and debugoff, containing an identical class with a
* debug() method. The first version displays its String argument to the console,
* the second does nothing. Use a static import line to import the class into a test
* program, and demonstrate the conditional compilation effect.
*/

/* In directory access/debugoff:
* // access/debugoff/Debug.java
* package access.debugoff;
*
* public class Debug {
*   public static void debug(String s) { }
* }
*/

package access.debug;

public class Debug {
    public static void debug(String s) {
        System.out.println(s);
    }
}


1.5 對使用包的忠告

包名對應路徑

二、Java訪問許可權修飾詞

public、protect和private 這幾個java方法許可權修詞在使用時,是為於類的成員定義之前,無論是域或方法。
如果不加任何詞修飾,則是包訪問許可權。

2.1 包訪問許可權

類的成員沒有指定修飾詞,具有包訪問許可權。這意味著該類當前包中所有其它類對該成員有訪問許可權,而該包外的其它類不能夠訪問。處於同一編譯單元中的類是能夠彼此方法的。嚴格的同一個包下才能訪問,同一個包下其它子目錄中的類無法訪問。

取得對該成員的訪問許可權方式有:
1. 使該成員為public。無論在哪裡都能夠訪問。
2.不加修飾詞。同一個包內的其它類都能訪問。
3。使用proteced修飾。可以被子類和同一包中的其它類訪問
4通過setter和getter訪問

2.2 public:介面訪問許可權

類成員使用 public 關鍵字修飾,意味著該成員能被其它任何類使用。
下面編譯dessert包

//: access/dessert/Cookie.java
// Creates a library.
package access.dessert;



public class Cookie {
  public Cookie() {
   System.out.println("Cookie constructor");
  }
  void bite() { System.out.println("bite"); }
} ///:~

使用Cookie的類:

//: access/Dinner.java
// Uses the library.
import access.dessert.*;

public class Dinner {
  public static void main(String[] args) {
    Cookie x = new Cookie();
    //! x.bite(); // Can't access
  }
} /* Output:
Cookie constructor
*///:~

Cookie類的構造器為public,因此可以訪問。Cookie類 dessert() 方法為包訪問許可權,因此不可以被訪問 。

預設包

//: access/Cake.java
// Accesses a class in a separate compilation unit.

class Cake {
  public static void main(String[] args) {
    Pie x = new Pie();
    x.f();
  }
} /* Output:
Pie.f()
*///:~

第二個處於相同目錄的檔案Pie.java

//: access/Pie.java
// The other class.

class Pie {
  void f() { System.out.println("Pie.f()"); }
} ///:~

可以正常編譯的原因是因為它們處於相同的目錄並且沒有指定包名,編譯器認為它們在該目錄下的預設包中。

2.3 private: 你無法訪問

private 關鍵字的含義是,除了包含該成員的類外,其它類都無法訪問。

Private允許自己隨意改變該成員,而不必考慮其它類。
使用private的示例。

//: access/IceCream.java
// Demonstrates "private" keyword.

class Sundae {
  private Sundae() {}
  static Sundae makeASundae() {
    return new Sundae();
  }
}

public class IceCream {
  public static void main(String[] args) {
    //! Sundae x = new Sundae();
    Sundae x = Sundae.makeASundae();
  }
} ///:~

將 Sundae 類構造器私有,防止別的類建立它,只能通過它提供的靜態方法makeASundae 建立。還可以阻止其它類繼承。

將類的輔助方法設為private,防止其它類使用。

2.4 protected 繼承訪問許可權

如果建立一個新包,並在新包中建立一個繼承其它包中類的繼承類,那麼該繼承類只能訪問父類public修飾的成員和protected修飾的成員。
protected 關鍵字提供包訪問許可權和子類訪問許可權。

之前例子Cookie.java 不可呼叫包訪問許可權bite()。

//: access/ChocolateChip.java
// Can't use package-access member from another package.
import access.dessert.*;

public class ChocolateChip extends Cookie {
  public ChocolateChip() {
   System.out.println("ChocolateChip constructor");
  }
  public void chomp() {
    //! bite(); // Can't access bite
  }
  public static void main(String[] args) {
    ChocolateChip x = new ChocolateChip();
    x.chomp();
  }
} /* Output:
Cookie constructor
ChocolateChip constructor
*///:~

將之前例子Cookie.java 中bite()方法進行修改為protected:

//: access/cookie2/Cookie.java
package access.cookie2;

public class Cookie {
  public Cookie() {
    System.out.println("Cookie constructor");
  }
  protected void bite() {
    System.out.println("bite");
  }
} ///:~

現在Cookie.java 中bite()方法對所有繼承它的類是可見的。

//: access/ChocolateChip2.java
import access.cookie2.*;

public class ChocolateChip2 extends Cookie {
  public ChocolateChip2() {
   System.out.println("ChocolateChip2 constructor");
  }
  public void chomp() { bite(); } // Protected method
  public static void main(String[] args) {
    ChocolateChip2 x = new ChocolateChip2();
    x.chomp();
  }
} /* Output:
Cookie constructor
ChocolateChip2 constructor
bite
*///:~

練習四

// access/CookieThief.java
// TIJ4 Chapter Access, Exercise 4, page 227
// Show that protected methods have package access but are not public.
/* In directory Cookie2:
* //access/cookie2/Cookie.java
* //Creates a library
* package access.cookie2;
*
* public class Cookie {
*   public Cookie() {
*       System.out.println("Cookie contstructor");
*   }
*   protected void bite() { System.out.println("bite"); }
* }
*/

import access.cookie2.*;

public class CookieThief {
    public static void main(String[] args) {
        Cookie x = new Cookie();
        //! x.bite(); // access protected
    }   
}

練習五

// access/AccessTest.java
// TIJ4 Chapter Access, Exercise 5, page 227 
/* Create a class with public, private, protected and package-access fields and
* method members. Create an object of this class and see what kind of compiler
* messages you get when you try to access all the class members. Be aware that
* classes in the same directory are part of the "default" package.
*/

/* in same directory:
* package access; 
*
* public class FourWays {
*   int a = 0;
*   public int b = 1;
*   protected int c = 2;
*   private int d = 3;
*   FourWays() { System.out.println("FourWays() constructor"); }
*   void showa() { System.out.println(a); }
*   public void showb() { System.out.println(b); }
*   protected void showc() { System.out.println(c); }
*   private void showd() { System.out.println(d); } 
* }
*/

package access; // run command java access.AccessTest

public class AccessTest {
    public static void main(String[] args) {
        FourWays fw = new FourWays();
        fw.showa();
        fw.showb();
        fw.showc();
        fw.a = 10;
        fw.b = 20;
        fw.c = 30;
        fw.showa();
        fw.showb();
        fw.showc();
        //! fw.showd(); // private access, compiler can't touch
    }   
}

//輸出
FourWays() constructor
0
1
2
10
20
30

練習六

// access/ProtectedData.java
// TIJ4 Chapter Access, Exercise 6, page 228
/* Create a class with protected data. Create a second class in the same file with
* a method that manipulates the protected data in the first class.
*/

class SomeData {
    protected int a = 13;
}

class DataChanger {
    static void change(SomeData sd, int i) { sd.a = i; }
}

public class ProtectedData {
    public static void main(String[] args) {
        SomeData x = new SomeData();
        System.out.println(x.a);                    
        DataChanger.change(x, 99);
        System.out.println(x.a);        
    }   
}
//輸出

三、介面和實現

將介面和具體實現分離,將public成員 放在最上方

//: access/OrganizedByAccess.java

public class OrganizedByAccess {
  public void pub1() { /* ... */ }
  public void pub2() { /* ... */ }
  public void pub3() { /* ... */ }
  private void priv1() { /* ... */ }
  private void priv2() { /* ... */ }
  private void priv3() { /* ... */ }
  private int i;
  // ...
} ///:~

四、類的訪問許可權

類的訪問許可權:
1.每個編譯單元(檔案)只能有一個public類。
2.public類的名稱必須與編譯單元檔名相同,包括大小寫
3. 編譯單元也可以沒有public類,這時檔名隨意命名。

將類的public屬性去掉,該類具有包訪問許可權。該類只能用於該包中

練習八

// MakeWidget.java
// TIJ4 Chapter Access, Exercise 7, page 230
/* Create the library according to the code fragments describing access and Widget.
* Create a Widget in a class that is not part of the access package.
*/

/* in access package:
* // access/Widget.java
* package access;
*
* public class Widget {
*   public Widget() { System.out.println("Widget()"); }
* }
*/

import access.*;

public class MakeWidget {   
    public static void main(String[] args) {
        Widget w = new Widget();
    }
}

如果將Widget中的public 關鍵字去掉,編譯會提示:

access\MakeWidget.java:20: 錯誤: Widget在access中不是公共的; 無法從外部程式包中對其進行訪問
                Widget w = new Widget();

Widget類具有包訪問許可權。

類僅有兩個選擇:包訪問許可權或public。不能用private或protected修飾。

將類的構造器設為私有阻止其它人建立物件,在類的static方法內部建立該物件。

示例Lunch.java

//: access/Lunch.java
// Demonstrates class access specifiers. Make a class
// effectively private with private constructors:

class Soup1 {
  private Soup1() {}
  // (1) Allow creation via static method:
  public static Soup1 makeSoup() {
    return new Soup1();
  }
}

class Soup2 {
  private Soup2() {}
  // (2) Create a static object and return a reference
  // upon request.(The "Singleton" pattern):
  private static Soup2 ps1 = new Soup2();
  public static Soup2 access() {
    return ps1;
  }
  public void f() {}
}

// Only one public class allowed per file:
public class Lunch {
  void testPrivate() {
    // Can't do this! Private constructor:
    //! Soup1 soup = new Soup1();
  }
  void testStatic() {
    Soup1 soup = Soup1.makeSoup();
  }
  void testSingleton() {
    Soup2.access().f();
  }
} ///:~

練習八

// access/ConnectionManager.java
// TIJ4 Chapter Access, Exercise 8, page 233
/* Following the form of the example Lunch.java, create a class called
* ConnectionManager that manages a fixed array of Connection objects. The client
* programmer must not be able to explicitly create Connection objects, but can
* only get them via a static method in ConnectionManager. When ConnectionManager
* runs out of objects, it returns a null reference. Test the classes in main(). */
package access;

class Connection {
    private static int count = 0;
    private int i = 0;
    private Connection() { System.out.println("Connection()");}
    // Allow creation via static method:
    static Connection makeConnection() {
        count++;
        return new Connection();
    }
    public static int howMany() { return count; } 
    public String toString() {
        return ("Connection " + count);
    }
}

public class ConnectionManager {
    static int howManyLeft = 3;
    static Connection[] ca = new Connection[3]; 
    {
    for(Connection x : ca)
        x = Connection.makeConnection();
    }
    public static Connection getConnection() {
        if(howManyLeft > 0)
            return ca[--howManyLeft];
        else {
            System.out.println("No more connections");
            return null;
        }
    }
    public static void main(String[] args) {        
        ConnectionManager cm = new ConnectionManager();
        System.out.println(cm.howManyLeft);
        cm.getConnection();
        System.out.println(howManyLeft);
        cm.getConnection();
        System.out.println(howManyLeft);
        cm.getConnection();
        System.out.println(cm.getConnection());
        System.out.println(howManyLeft);
    }                   
} 

輸出:
Connection()
Connection()
Connection()
3
2
1
No more connections

相關推薦

java程式設計思想 6 訪問許可權控制

更新類庫時為了讓開發人員知道哪些類是被其它類引用的,不能被修改而引人了訪問許可權控制。 public > protect >(預設) > private 一、包:庫單元 包內包含一組類、它們在單一的名稱空間下被組織到了一起: jav

Java程式設計思想訪問許可權控制練習題解答(待更新完整.......)

練習解答 練習1 練習2 練習3 練習1 先在另一個包建立程式碼,命名為ch6Ex1.java package ch5; public class ch6Ex1 { public ch6Ex1()

java程式設計思想——(訪問許可權控制)》

訪問許可權控制 6.1包:庫單元 包內包含有一組類,它們在單一的名字空間之下被組織在了一起。 6.2訪問許可權修飾詞 包訪問許可權:當前包中所有的類都可以訪問。 public:所有的類都可以訪問。 private:自由類自己的成員可以訪問。

Thinking in Java 6 訪問許可權控制 【包:庫單元】

//宣告:部分內容引自《Java程式設計思想(第四版)》機械工業出版社 – 當編寫一個 Java 原始碼檔案時,此檔案通常被稱為編譯單元(有時也被稱為轉譯單元)。每個編譯單元都有一個字尾名 .java。 – 當編譯一個 .java 檔案時,在 Java 檔案

Java程式設計思想(六)—— 訪問許可權控制

一、包:庫單元         包內含有一組類,它們在單一的名字空間下被組織在了一起。例如,在Java的標準釋出中有一個工具庫,它被組織在java.util名字空間下,如果要使用此名字空間下的ArrayList類,可以使用其命名的方式,如下: pu

Java程式設計思想 訪問許可權控制

一個優秀的程式設計師是通過不斷的重構程式碼讓自己的程式變得更加易用、可讀和完善的。在重構修改的過程中,如果是一個類庫編寫人員,那麼怎麼樣保證自己修改的部分不會影響到客戶端編寫人員(即使用這個類庫的程式設計師)呢?同時也要避免他們對自己類庫內部的程式進行改動。Java中提供了訪問許可權控制的概

Java程式設計思想之讀書筆記系列四 --- --- 訪問許可權控制

這是Java程式設計思想之讀書筆記系列的第四篇,主要記錄了第六章訪問許可權控制的相關內容。具體內容如下:面向物件設計中需要考慮的一個基本問題:如何把變動的事物與保持不變的事物區分開來Java提供了訪問許

Java程式設計思想》筆記之——訪問許可權控制

本文只摘錄很少一部分,作文筆記。訪問控制(或隱藏具體實現)與“最初的實現並不恰當”有關當編寫一個Java原始碼檔案時,此檔案通被稱為編譯單元(有時也被稱為轉譯單元)。每個編譯單元都必須有一個字尾名為.java,而編譯單元內測可以有一個public類,該類的名稱必須與檔名稱相同

Java程式設計思想筆記】-訪問許可權控制

要學會把變動的程式碼與保持不變的程式碼區分開來。 如果有必要,你儘可能將一切方法都定為private。 非public類在其它包中是訪問不到的。 所有預設包的類都是屬於同一個包,儘管它們在不同的資料夾下面。 private,只允許本類所有物件可訪問,其他任何類

Java程式設計思想 訪問許可權控制

第六章 訪問許可權控制 ​ 重構即重寫程式碼,以使得它更可讀、更易理解,並因此而更具可維護性。 ​ Java提供了訪問許可權修飾詞,以供類庫開發人員向客戶端程式設計師指明哪些是可用的,哪些是不可用的。訪問許可權控制的等級,從最大許可權到最小許可權依次為:pub

JAVA程式設計思想-複用類

1.一個物件被轉換成string時,會呼叫物件的toSting方法 public class demo7 { private water w=new water(); private String s="string"; public static void main(Strin

java程式設計思想——十三(字串)》

字串## 13.1 不可變String## string物件是不可變。String類中每一個看起來會修改String值得方法,實際上都建立了一個新的String物件。 public class Immutable {; public static String upcas

java程式設計思想——(內部類)》

內部類 可以將一個類的定義放在另一個類的定義內部,這就是內部類。 10.1 建立內部類 把類的定義置於外圍類的裡面。 /** * 建立內部類 * @author Administrator */ public class Parcel1 { class Co

關於Java程式設計思想中 net.jar的匯入

首先右擊你需要匯入net.jar的Eclipse專案,選擇      “構建路徑”-   -“配置構建路徑”  。點選    “庫”   選項卡,單擊右邊的“新增外部JAR”按鈕,然後找到你的 net

Java程式設計思想複用類練習題解答

練習題解答 練習1 練習2 練習3 練習4 練習5 練習6 練習7 練習8 練習9 練習10 練習11 練習12 練習13 練習14 練習15

Java程式設計思想初始化與清理練習題解答

目錄 1、構造器 練習1 練習2 3、方法過載 練習3 練習4 練習5 練習6 練習7 練習8 練習9 練習10 練習14 練習16

Java 程式設計思想筆記

                                                第三章操作符 一邊做筆記一邊看書,打程式碼更好 第六章靜態匯入是什麼? 3.1 以前我就一直覺得 System 的輸出語句太長了,作者在這裡為我完美的解決了問題,利用靜態匯入這

Java 程式設計思想筆記

    第四章執行控制流程     程式在執行過程中控制他的世界,利用執行控制語句。     Java 使用了 C語言中的所有流程控制語句,Java中設計的關鍵字 if-else while do-while for return break 以及選擇語句 switch。

Java 程式設計思想

                                                                       第五章初始化與清理     初始化與清理是設計安全的兩個問題,C語言中如果使用者不知如何初始化庫的構建,另外資源的佔用,忘記了釋放導

Java程式設計思想 :多型

OOP語言中,多型是封裝、繼承之後的第三種基本特徵。 封裝:通過合併特徵和行為來建立新的資料型別,“實現隱藏”通過細節“私有化”把介面和實現分離 繼承:以複用介面方式從已有型別用extends關鍵字建立新型別,並允許向上轉型 多型:消除型別之間的耦合關係(分離做什麼和怎麼做),基