Java 從入門到進階之路(十二)
在之前的文章我們介紹了一下 Java 類的重寫及與過載的區別,本章我們來看一下 Java 類的 private,static,final。
我們在之前引入 Java 類概念的時候是通過商場收銀臺來引入的,如下:
如果我們使用刷卡的形式進行付賬,我們需要出示一張有足夠餘額的銀行卡或者會員卡來進行付款,在付款的時候我們僅僅是通過刷卡,輸入密碼來完成支付,在這個過程中,收銀員是不能看到我們的卡號,密碼,餘額這些私密性的資料,否則可能會出現被盜刷或者其他問題,收銀員在收銀的時候只需要做的就是我們輸入密碼時對我們輸入的密碼與原始密碼時候匹對和賬戶餘額是否大於等於商品價格就可以了。
根據上面的分析我們我們可以定義一個 Card 類:
1 class Card{ 2 private String cartId; // 卡號 3 private String cardPwd; // 密碼 4 private double balance; // 餘額 5 public boolean payMoney(double money){ // 支付 6 if(balance >= money){ 7 balance -= money; 8 return true; 9 } 10 return false; 11 12 } 13 public boolean checkPwd(String pwd){ // 檢查密碼 14 if(cardPwd.equals(pwd)){ 15 return true; 16 } 17 return false; 18 } 19 }
在上面的程式碼中,我們將變數前的修飾詞寫成了 private,將方法前的修飾詞寫成了 public。接下來我們看一下 private 和 public 之間的區別。
private 修飾從成員變數和方法只能在本類中呼叫,public 修飾的成員變數和方法可以在任何地方呼叫。
private 修飾的內容是對內實現的封裝,public 修飾的內容是對外提供可以被呼叫的功能。
另外還有兩種:protected 和 預設不寫,我們稱之為訪問控制修飾符,他們的控制範圍分別是:
1)public:公開的,任何類
2)private:私有的,本類
3)protected:受保護的,本類、子類、同包類
4)預設的(什麼也不寫):本類、同包類
接下來我們看一下關鍵字 static 。
之前我們在類中定義的變數其實可以叫做例項變數,還有一種變數叫做靜態變數,即用 static 關鍵字修飾。我們先來看一下兩種變數之間的區別:
1、例項變數:
1)屬於物件的,存在對重
2)有幾個物件就有幾份例項變數
3)必須通過 物件名. 來訪問
2、靜態變數:
1)屬於類的,存在方法區中
2)只有一份
3)必須通過 類名. 來訪問
我們通過下面的程式碼來實際看一下:
1 public class HelloWorld { 2 public static void main(String[] args) { 3 Aoo aoo1 = new Aoo(); 4 aoo1.show(); // a=1 b=1 5 6 Aoo aoo2 = new Aoo(); 7 aoo2.show(); // a=1 b=2 8 } 9 } 10 11 class Aoo { 12 int a; 13 static int b; 14 15 Aoo() { 16 a++; 17 b++; 18 } 19 20 void show() { 21 System.out.println("a=" + a); 22 System.out.println("b=" + b); 23 } 24 }
在上面的程式碼中我們分別定義了例項變數a 和靜態變數b,然後例項化了兩次 Aoo,再通過兩次呼叫例項化 Aoo 後呼叫 show() 方法可以看出我們例項化後呼叫的例項變數 a 的值不變,即每例項一次就會複製出一個 a,而靜態變數 b 則每例項化一次後值會變化,即例項化後並不會重新複製一個 b,而是繼續使用上一次的。
接下來我們看一下 static 關鍵字的靜態方法。
靜態方法和上面的靜態變數大體上相同,但也有特殊的地方。
1)屬於類的,存在方法區中
2)只有一份
3)必須通過 類名. 來訪問
4)沒有隱式的 this 傳遞,靜態方法中不能直接訪問例項變數
1 class Aoo { 2 int a; // 例項變數---物件點訪問 3 static int b; // 靜態變數---類名點訪問 4 5 void test1() { // 例項方法 6 a++; 7 b++; 8 } 9 10 static void test2() { // 靜態方法 11 a++; // 編譯錯誤 12 test1(); // 編譯錯誤 13 b++; 14 } 15 }
在上面的程式碼中,我們通過 static 關鍵字將變數 b 變為靜態變數,將 test2() 變為靜態方法,當我們在 test1() 的例項方法中 a++ 和 b++ 時,系統會預設為我們寫成 this.a++ 和 Aoo.b++;而在 test2() 中,由於靜態方法沒有隱式 this,所以 a++ 和 test1() 方法並沒有。
接下來我們看一下 static 關鍵字的靜態塊。
1 public class HelloWorld { 2 public static void main(String[] args) { 3 Aoo aoo1 = new Aoo(); // 靜態塊 構造方法 4 Aoo aoo2 = new Aoo(); // 構造方法 5 } 6 } 7 8 class Aoo { 9 static { 10 System.out.println("靜態塊"); 11 } 12 13 Aoo(){ 14 System.out.println("構造方法"); 15 } 16 }
在上面的程式碼中,我們在 Aoo 中建立了一個構造方法,並且通過 static { } 建立了一個靜態塊,我們例項化了兩個 Aoo 類,我們發現靜態塊只加載一次,而靜態方法每例項化一次就載入一次。
靜態塊在實際應用中可以載入圖片,音訊,視訊等靜態資源,比如我們逛淘寶時圖片只加載一次,不可能每個人近義詞淘寶網站就載入一次,伺服器壓力也受不了。
接下來我們來看一下 final 關鍵字。
1、final 修飾成員變數,兩種方式初始化:
1)宣告的同事初始化
2)構造方法中初始化
2、final 修飾區域性變數,只要在用之前初始化即可。
程式碼如下:
1 class Aoo { 2 int a = 10; 3 int b; 4 final int c = 10; // 宣告同時初始化 5 // final int d; // 編譯錯誤 宣告未初始化 6 final int e; 7 8 Aoo() { 9 e = 10; // 構造方法中初始化 10 } 11 12 void test() { 13 final int f; // 區域性變數:用之前賦值即可,不用刻意不用賦值 14 a = 20; 15 // c = 20; // 編譯錯誤,final 修飾變數不能被改變 16 } 17 18 }
final 修飾方法:final 修飾方法不能被重寫。
程式碼如下:
1 class Aoo { 2 void test(){} 3 final void show(){} 4 } 5 6 class Boo extends Aoo{ 7 void test(){} 8 void show(){} // 編譯錯誤,final 方法不能被重寫 9 }
final 修飾類:final 修飾的類不能被繼承,但是能繼承其他類
程式碼如下:
1 class Aoo {} 2 class Boo extends Aoo{} 3 final class Coo extends Aoo{} // final 修飾的類可以繼承別的類 4 5 final class Doo{} 6 class Eoo extends Doo{} // 編譯錯誤,final 修飾的類不能被繼承