Java面向對象以內部類—inner classide
Java 類
中的能夠定義的成員有:字段、方法、內部類
,內部類是定義在類結構中的另外一個類,由於定義在類的內部,故稱爲內部類。this
public class OuterClass { ...... public class InnerClass { ...... } }
在上述的代碼示例中,就能夠將InnerClass
稱之爲OuterClass
的內部類。spa
爲何使用內部類:code
在Java
中的LinkedList
的源碼中,使用一個內部類Node
來封裝鏈表列表中的每個節點,在節點中存儲了當前節點的值,上一個節點,下一個節點這些信息;而這些信息是不能外部對象直接讀取和使用的,所以,使用內部類封裝隱藏是一個不錯的選擇。對象
內部類的分類:內部類根據使用的修飾符的不一樣,或者定義的位置的不一樣,分紅四種類型;繼承
static
修飾,也就是非靜態內部類,定義在類中,方法以外;static
修飾,定義在類中,方法以外,而且使用static
修飾;對於每一個內部類來講,通過JVM
編譯後都會生成獨立的.class字節碼文件
,由於JVM
會爲每個類產生各自的字節碼文件。接口
內部類其實就是外部類的一個成員,跟字段、方法同樣的存在,那麼內部類可使用訪問控制修飾符:public/缺省/protected/private和static修飾符
修飾。事件
實例內部類:沒有使用static
修飾的內部類,實例內部類屬於外部類的對象,不屬於外部類自己;能夠經過外部類對象來訪問。其特色是:內存
1.在實例化內部類以前,必須存在外部類對象,由於要經過外部類對象建立內部類對象,因此存在內部類對象時,必定存在外部類對象;作用域
OutterClass.InnerClass in = new OutterClass().new InnerClass();
2.實例內部類的實例自動持有外部類的實例的引用,因此內部類能夠直接訪問外部類成員;
3.外部類中不能直接訪問內部類的成員,必須經過內部類的實例去訪問;
4.實例內部類中不能定義靜態成員,只能定義實例成員(非靜態成員);
5.若是實例內部類和外部類存在同名的字段或方法abc
,那麼在內部類中:
實例內部類代碼案例以下:
public class OuterClass { // 外部類成員 String name = "Outer.name"; public void printInnterName() { // 訪問內部類成員 System.out.println(this.new InnerClass().name); } public class InnerClass { String name = "InnerClass.name"; public void printName() { String name = "name"; System.out.println(name); System.out.println(this.name); System.out.println(OuterClass.this.name); } } }
靜態內部類:使用static
修飾的內部類,這點有別於實例內部類,須要特別注意。其特色是:
1.靜態內部類的實例不會自動持有外部類的特定實例的引用,所以在建立內部類的實例時,沒必要建立外部類的實例。
OutterClass.InnerClass in = new OutterClass.InnerClass();
2.靜態內部類能夠直接訪問外部類的靜態成員,若是要訪問外部類的實例成員,仍是必須經過外部類的實例去訪問。
3.在靜態內部類中能夠同時定義靜態成員和實例成員。
4.外部類能夠經過完整的類名直接訪問靜態內部類的靜態成員。
靜態內部類代碼案例以下:
public class OuterClass { // 外部類成員 String name = "Outer.name"; // 外部類靜態成員 static String name2 = "Outer.name2"; public static class InnerClass { public void printName() { System.out.println(name2); System.out.println(new OuterClass().name); } } }
局部內部類:在方法中定義的內部類,其做用域範圍和當前方法及其當前方法的局部變量是同一個級別。不過局部內部類使用的較少,在開發中也不推薦使用。
public、private、protected、static
等這些修飾符;final
修飾,在Java8
中是自動隱式加上final
,可是依然是常量,值不能被改變;爲何不推薦使用局部內部類?由於若是當前方法不是main方法
,那麼當前方法調用完畢以後,當前方法的棧幀會被銷燬,方法內部的局部變量的空間也會所有銷燬。
然而局部內部類是定義在方法中的,在方法中會建立局部內部類對象,局部內部類對象會去訪問局部變量;若是當前方法被銷燬,局部內部類對象還在堆內存中,依然持有對局部變量的引用,可是方法被銷燬的時候方法中的局部變量卻被銷燬了。
此時就會出現:在堆內存中,一個對象引用着一個不存在的變量,爲了不該問題,可使用final
修飾局部變量,從而變成常量,使之永駐內存空間,這樣即便方法被銷燬了,該局部變量也繼續存在在內存中,對象能夠繼續持有。
局部內部類代碼案例以下:
public class LocalInnerClass { // 外部類靜態成員 static String name = "name"; public static void main(String[] args) { System.out.println("局部內部類"); final String info = "info"; class InnerClass { String nick = "nick"; System.out.println(name); System.out.println(info); System.out.println(nick); } new InnerClass().test(); } }
匿名內部類(Anonymous),是一個沒有名稱的局部內部類,適合只使用一次的類。在開發中會常用這樣的類,只須要定義一次,僅僅使用一次就能夠再也不使用了,此時就不該該再定義在一個類來存儲其功能邏輯。好比在Android的事件處理中,不一樣的按鈕點擊以後產生的不一樣的響應操做,首先選擇使用匿名內部類。
匿名內部類的語法格式:
new 父類構造器([實參列表]) 或 接口(){ //匿名內部類的類體部分 }
可是須要注意的是:匿名內部類必須繼承一個父類或者實現一個接口,但其最多隻能繼承一個父類或實現一個接口。
匿名內部類的特色:
JVM
在調用父類構造器後,會執行該段代碼;匿名內部類代碼案例以下:下述代碼是安卓中的按鈕點擊事件處理邏輯
btnClick.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Toast.makeText(MainActivity.this, "按鈕被點擊", Toast.LENGTH_SHORT).show(); } });
完結。老夫雖不正經,但老夫一身的才華