在之前的文章我們介紹了一下 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 修飾的類不能被繼承
