java學習筆記(三)內部類及靜態內部類
內部類的建立:
內部類 物件名 = 外部類物件.new 內部類();
外部類是不能使用內部類的成員和 方法
如果外部類和內部類具有相同的成員變數或方法,內部類預設
訪問自己的成員變數 或方法,如果要訪問外部類的成員變數,
可以使用this關鍵字。
//外部類HelloWorld public class HelloWorld{ //外部類的私有屬性name private String name = "imooc"; //外部類的成員屬性 int age = 20; //成員內部類Inner public class Inner { String name = "愛慕課"; //內部類中的方法 public void show() { System.out.println("外部類中的name:" + this.name ); System.out.println("內部類中的name:" + name ); System.out.println("外部類中的age:" + age); } } //測試成員內部類 public static void main(String[] args) { //建立外部類的物件 HelloWorld o = new HelloWorld (); //建立內部類的物件 Inner inn = o.new Inner(); ; //呼叫內部類物件的show方法 inn.show(); } }
靜態內部類:
靜態內部類是 static 修飾的內部類,這種內部類的特點是:
1、 靜態內部類不能直接訪問外部類的非靜態成員,但可以通過 new 外部類().成員 的方式訪問
2、 如果外部類的靜態成員與內部類的成員名稱相同,可通過“類名.靜態成員”訪問外部類的靜態成員;如果外部類的靜態成員與內部類的成員名稱不相同,則可通過“成員名”直接呼叫外部類的靜態成員
3、 建立靜態內部類的物件時,不需要外部類的物件,可以直接建立 內部類 物件名= new 內部類();
public class HelloWorld { // 外部類中的靜態變數score private static int score = 84; // 建立靜態內部類 public static class SInner { // 內部類中的變數score int score = 91; public void show() { System.out.println("訪問外部類中的score:" + HelloWorld.score); System.out.println("訪問內部類中的score:" + score); } } // 測試靜態內部類 public static void main(String[] args) { // 直接建立內部類的物件 SInner si = new SInner(); // 呼叫show方法 si.show(); } }
靜態變數(類)與非靜態變數(類)的區別以及為什麼要使用靜態變數(來源:imooc問答區):
一般靜態變數都是公用的、全域性的,程式一啟動就會在記憶體開闢一塊空間,存放它們。靜態的不必例項化就能直接使用,是說在沒有生成任何物件時就能運用該方法,所以靜態方法裡不能對非靜態的成員變數做操作。一般靜態方法操作靜態成員變數或全域性變數。
要搞清楚這個問題,我們需要清楚他們之間有什麼區別,有什麼優勢和劣勢。
首先看看靜態與非靜態方法的區別:
靜態方法 | 例項方法
1、靜態方法可以通過“類.方法()”呼叫 | 要在物件例項化後使用物件呼叫
2、只能使用靜態變數和區域性變數 | 所有變數都可以使用
3、靜態方法不能被子類重寫 | 例項方法可以
4、介面不能定義靜態方法 | 例項方法可以
從上面區別來看,靜態方法只有一個優勢,就是呼叫的時候不用例項化,其他情況下跟例項方法相比都是處於劣勢。那麼我們在什麼情況下會使用到靜態方法?相信大家第一時間會想到一樣的東西,工具類Util。工具類給我們開發帶來了大大的方便,歸根到底是“不用例項化就能用”的功勞。這是靜態方法的一個優勢。
而靜態方法的劣勢也很明顯,侷限性很大,不能重寫,不能引用普通變數,介面不能定義等等。。。可能還有很多我沒列舉出來。
那究竟什麼時候該用靜態方法?我們就要最大化利用其優勢而避其缺點:
1、一個方法完成一個獨立的功能,而且不會干擾到其他方法或變數,則即使刪掉這個方法,對其他東西都沒有任何影響。
2、不依賴構造方法,不依賴介面,不依賴繼承。(這也是為什麼越學面向物件,越會糾結這個問題)
舉個例子:String類即使刪掉 static valueOf(Object obj)方法,也不會影響例項方法chatAt(int index)的使用。當然它可能會影響其他過載的valueOf方法。
至於現在網上很多資料都有一個誤區,就是說靜態方法一開始載入,會佔用記憶體,而例項方法不會。這個說話其實是錯誤的,它們都是一樣一開始就會載入,而且只會佔用一份記憶體。因為方法不是變數,它只需要有一份記憶體就夠了。而變數則不一樣
-----------------------------------------------------------------------------------------------------------------------------------------------------------
下面來看看靜態變數與非靜態變數
靜態變數 | 非靜態變數
1、可以通過“類.變數”來引用。 | 只能通過例項物件來引用。
2、程式執行時分配記憶體 | 類例項化時分配記憶體。
3、只有一份記憶體被分配 | 有多少個類被例項化,就有多少個該類的變數那麼多份記憶體被分配。
4、靜態變數定義後必須宣告初始化 | 非靜態變數可以延遲初始化。
其他.....
很明顯,靜態變數擁有的優勢不少,第一點不用說。第2、3點可以利用它來做一個整個程式的全域性變數,因為任何修改都只會指向同一份記憶體。
而第3點優勢恰好就是我們的“餓漢式單例模式”的一個最簡單的實現。