Java編程思想 訪問權限控制

訪問權限控制

1.Java文件組織

.java文件: 一個包中有多個.java文件,每個java文件都是一個編譯單元。編譯一個.java文件時,.java文件中的每個類都會有一個輸出文件,輸出文件名稱和.java文件中每個類的名稱相同,只是多一個後綴名.class。每個編譯單元內只能有一個public類,該類的名稱必須與文件的名稱相同(包括大小寫)。非public類對包外不可見,主要爲public class服務。

可運行程序:是一組可以打包並壓縮爲一個Java文檔文件的.class文件。

package: 類庫是一組類文件,每個文件都有一個public類,以及任意數量的非public類。因此每個文件都有一個構件。若將這些構件(每一個都有自己獨立的.java和.class文件)從屬於同一個羣組,就可以使用關鍵字package。除註釋外的第一行代碼,在文件起始處寫。

注意Java包的命名全部選用小寫字母。

2.類庫的使用

使用import關鍵字:import java.lang.* import java.util.ArrayList

條件編譯:不改變程序代碼,可以切換開關產生不同的行爲,如調試功能。

3.包權限訪問修飾詞

pubic、protected、friendly、private

包訪問權限:
  • 如果包中成員爲public,則包及包之外都可以訪問該成員。
  • 如果包中成員爲friendly,則只有包之內的才能對其進行訪問。
  • 如果包中成員爲private,則只有包含該成員的類才能對其進行訪問。——但是可以通過訪問器(accessor)和變異器(mutator)方法(get/set)讀取或者改變原來的值。
  • 繼承的類可以訪問protected和public成員
//get、set方法
public class User{
    private String username;
    private int age;
    public void setUsername(String username){
        this.username = username;
    }
    public char getUsername(String username){
        return username;
    }
}

類的訪問權限修飾符:public friendly

成員變量和成員方法訪問權限修飾符:private public protected friendly

4.重點程序 lunch.java:
class Soup1{
    private Soup1() {}//構造器私有化
    public static Soup1 makesoup(){//用static方法不創建對象,調用構造器
        return new Soup1();
    }
}
class Soup2{
    private Soup2() {}
    private static Soup2 ps1 = new Soup2();
    //私有的靜態對象,容易忘記ps1是靜態的
    public static Soup2 access(){
        return ps1;//只能訪問唯一的Soup2對象
    }
    public void f() {}
}
public class Lunch{
    void testStatic() {
        Soup1 soup = Soup1.makesoup();//靜態方法創建對象,可創建多個
    }
    void testSingleton() {
        Soup2.acess().f();//只可以訪問唯一的一個對象
    }
}
5.包名的編碼和解析

包名的第一部分是類的創建者的反順序的域名。

第二部分是將package名稱分解爲機器上的一個目錄。當Java程序運行需要加載class文件時,可以確定文件在目錄上所處的位置。首先,Java解釋器將找出環境變量CLASSPATH,CLASSPATH包含一個或多個目錄,用作查找.class文件的根目錄。從根目錄開始,解釋器獲取包的名稱並將每個句點替換成反斜槓,以從CLASSPATH根中產生一個路徑名稱。

6.封裝

封裝:封裝是指把數據成員和相關方法都放進一個類中,並使用訪問權限來控制其可見性。

第六章 複用類

1.組合

在新類中使用現有類的對象作爲成員變量。由於新的類是有現有類的對象組成,所以這種方法稱爲組合。

組合複用的是功能

對象引用的三種初始化方法:

  • 指定初始化:

定義對象的地方進行初始化,這意味着在構造器調用之前他們完成了初始化。

  • 構造器初始化:

構造器中初始化對象。

  • 懶惰初始化

就在正要使用對象之前,進行初始化。對象引用初始化爲NULL。

2.繼承

按照現有類的類型創造新類。不改變類的形式,增加新的成員變量和方法。

繼承複用的是接口。

爲便於繼承,成員變量定義爲private,方法定義爲public。

2.1 extends 和 super 關鍵字用法:
class Cleanser{
    public void scrub() {}
}
public class Detergent extends Cleanser{//用extends
    public void scrub(){
        append("Detergent.scrub()");
        super.scrub();//調用基類的方法
    }
}

super用於調用基類的方法,和在基類構造器帶參數的情況下,在派生類構造器中顯式調用基類構造器

class Game{
    Game(int i) {
    }
}
class BoardGame extends Game{
    BoardGame(int i){
        super(i);
    }
}
//或者也可以
class ComputerGame extends Game{
    Computer(){
        super(11);
    }
}
2.2 名稱屏蔽

如果Java中基類已經擁有某個已被多次重載的方法名稱,那麼在導出類中重新定義該方法並不會屏蔽在基類中的任何版本(這一點與C++不同)。

重寫是重新覆蓋父類的方法,在一些子類要實現的方法中,方法名、參數列表和返回值類型都和父類的方法一樣,但具體實現與父類不同,這時候就需要重寫父類的方法。

如果沒有重寫,那麼子類調用一個子類沒有的方法時,實際上是在調用父類。

以下是方法重載的一個例子。

class Homer {
    char doh(char 'c') {
        print("doh(char)");
    }
    float doh(float f) {
        print("doh(float)");
    }
}
class Milhouse {}
class Bart extends Homer {
    void doh(Milhouse m) {
        print("doh(Milhouse)");
    }
}
public class Hide{
    public static void main(String[] args) {
        Bart b = new Bart();
        b.doh(1);//doh(float)
        b.doh('x');//doh(char)
        b.doh(new Milhouse());//doh(Milhouse)
    } //不能構造b.doh(0.2324);可以構造b.doh(0.2324f);
}
2.3 基類中的protected成員和方法可以被派生類訪問
3.final關鍵字
3.1 final數據

對於基本類型,final使基本類型的數值不發生改變。

對於對象引用,final使引用恆定不變。但是對象的數值是可以修改的。

必須在域的定義處或者每個構造器中用表達式對final進行賦值。

注意:是每個構造器!

final與static:

對於常量,兩者差別不大。最好使用public static final來聲明常量。

帶有恆定初始值的final static常量全部用大寫字母命名,單詞之間用下劃線隔開。

private final int valueone = 9;
private static final int VAULE_TWO = 99;

對於特殊變量:也不能認爲某數據是final的,所以一定可以在編譯前知道它的值。

private final int i4 = rand.nextInt(20);
//每次new新對象時值會改變,對於同一個對象值不變
private static final int INT_5 = rand.nextInt(20);
//對於所有創建的對象,經過第一次創建對象初始化後,值永遠不會發生改變。
final參數:

Java允許在參數列表中,以聲明的方式將參數指明爲final。這意味着將無法在方法中更改引用所指向的對象。

3.2 final方法

目的:鎖定方法,防止派生類修改;考慮效率,如果一個方法是final的,所有對該方法的調用都轉爲內嵌調用。

3.3 final類

不可以被繼承

4.基類的初始化

(1)在創建派生類對象時,該對象包含一個基類的子對象。基類的子對象的初始化是通過調用基類構造器實現,自動在派生類的構造器中插入對基類構造器的調用。

(2)基類的構造器在派生類構造器之前被調用。

(3)如果沒有默認的構造器或構造器帶參數必須顯式的調用。

class Insect {
  int i = 9;
  int j;
  int m = prt("Insect.m initialized");
  Insect() {
    prt("i = " + i + ", j = " + j);
    j = 39;
  }
  static int x1 = 
    prt("static Insect.x1 initialized");
  static int prt(String s) {
    System.out.println(s);
    return 47;
  }
}

public class Beetle extends Insect {
  int k = prt("Beetle.k initialized");
  int l = prt("Beetle.l initialized");
  Beetle() {
    prt("k = " + k);
    prt("j = " + j);
  }
  static int x2 =
    prt("static Beetle.x2 initialized");
  public static void main(String[] args) {
    prt("Beetle constructor");
    Beetle b = new Beetle();
  }
} 

第一步:訪問Beetle.main()函數

第二步:加載器啓動並找出Beetle類的編譯代碼(在Beetle.class中)

第三步:繼續加載基類Insect.class

第四步:對基類中的static進行初始化

第五步:對派生類中的static進行初始化

第六步:創建對象

第七步:將對象的內存設爲二進制零值,所有的基本類型設爲默認值,所有的引用設爲NULL

第八步:基類實例變量初始化

第九步:調用基類構造器

第十步:派生類實例變量初始化

十一步:調用派生類構造器

執行結果:

static Insect.x1 initialized
static Beetle.x2 initialized
Beetle constructor
Insect.m initialized
i = 9, j = 0
Beetle.k initialized
Beetle.l initialized
k = 47
j = 39
發佈了48 篇原創文章 · 獲贊 13 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章