做爲剛入門Java的小白,這兩天看到內部類,這裏作一個總結,如有錯誤,歡迎指正~java
內部類是指在一個外部類的內部再定義一個類。類名不須要和文件夾相同。ide
內部類分爲: 成員內部類、局部內部類、靜態嵌套類、匿名內部類 。this
1.成員內部類spa
成員內部類是最普通的內部類,它的定義爲位於另外一個類的內部,形以下面的形式:對象
class Outter { private int age = 12; class Inner { private int age = 13; public void print() { int age = 14; System.out.println("局部變量:" + age); System.out.println("內部類變量:" + this.age); System.out.println("外部類變量:" + Outter.this.age); } } } public class test1 { public static void main(String[] args) { Outter out = new Outter(); Outter.Inner in = out.new Inner(); in.print(); } }
運行結果:blog
局部變量:14
內部類變量:13
外部類變量:12繼承
從本例能夠看出:成員內部類,就是做爲外部類的成員,能夠直接使用外部類的全部成員和方法,即便是private的。雖然成員內部類能夠無條件地訪問外部類的成員,而外部類想訪問成員內部類的成員卻不是這麼爲所欲爲了。在外部類中若是要訪問成員內部類的成員,必須先建立一個成員內部類的對象,再經過指向這個對象的引用來訪問:接口
class Outter { private int age = 12; public Outter(int age) { this.age = age; getInInstance().print(); //必須先建立成員內部類的對象,再進行訪問! } private Inner getInInstance() { return new Inner(); } class Inner { public void print() { System.out.println("內部類沒同名,因此直接調用外部類成員變量:" + age); } } } public class test1 { public static void main(String[] args) { Outter out = new Outter(10); } }
運行結果:生命週期
內部類沒同名,因此直接調用外部類成員變量:10事件
內部類能夠擁有private訪問權限、protected訪問權限、public訪問權限及包訪問權限。
好比上面的例子,若是成員內部類Inner用private修飾,則只能在外部類的內部訪問,若是用public修飾,則任何地方都能訪問;若是用protected修飾,則只能在同一個包下或者繼承外部類的狀況下訪問;若是是默認訪問權限,則只能在同一個包下訪問。
這一點和外部類有一點不同,外部類只能被public和包訪問兩種權限修飾。
我我的是這麼理解的,因爲成員內部類看起來像是外部類的一個成員,因此能夠像類的成員同樣擁有多種權限修飾。要注意的是,成員內部類不能含有static的變量和方法。由於成員內部類須要先建立了外部類,才能建立它本身的
2.局部內部類
局部內部類是定義在一個方法或者一個做用域裏面的類,它和成員內部類的區別在於局部內部類的訪問僅限於方法內或者該做用域內。
定義在方法裏的內部類:
class Outter { private int age = 12; public void Print(final int x) { //這裏局部變量x必須設置爲final類型! class Inner { public void inPrint() { System.out.println(x); System.out.println(age); } } new Inner().inPrint(); } } public class test1 { public static void main(String[] args) { Outter out = new Outter(); out.Print(10); } }
運行結果:
10
12
本例中咱們將內部類移到了外部類的方法中,而後在外部類的方法中再生成一個內部類對象去調用內部類方法。若是此時咱們須要往外部類的方法中傳入參數,那麼外部類的方法形參必須使用final定義。
換句話說,在方法中定義的內部類只能訪問方法中final類型的局部變量,這是由於在方法中定義的局部變量至關於一個常量,它的生命週期超出方法運行的生命週期,因爲局部變量被設置爲final,因此不能再內部類中改變局部變量的值。(這裏看到網上有不一樣的解釋,尚未完全搞清楚==)
定義在做用域內的內部類:
class Outter { private int age = 12; public void Print(final boolean x) { //這裏局部變量x必須設置爲final類型! if(x){ class Inner { public void inPrint() { System.out.println(age); } } new Inner().inPrint(); } } } public class test1 { public static void main(String[] args) { Outter out = new Outter(); out.Print(true); } }
運行結果:12
3.靜態嵌套類
又叫靜態局部類、嵌套內部類,就是修飾爲static的內部類。聲明爲static的內部類,不須要內部類對象和外部類對象之間的聯繫,就是說咱們能夠直接引用outer.inner,即不須要建立外部類,也不須要建立內部類。
class Outter { private static int age = 12; static class Inner { public void print() { System.out.println(age); } } } public class test1 { public static void main(String[] args) { Outter.Inner in = new Outter.Inner(); in.print(); } }
運行結果:
12
能夠看到,若是用static 將內部內靜態化,那麼內部類就只能訪問外部類的靜態成員變量,具備侷限性。
其次,由於內部類被靜態化,所以Outter.Inner能夠當作一個總體看,能夠直接new 出內部類的對象(經過類名訪問static,生不生成外部類對象都不要緊)
4.匿名內部類
匿名內部類應該是平時咱們編寫代碼時用得最多的,在編寫事件監聽的代碼時使用匿名內部類不但方便,並且使代碼更加容易維護。下面這段代碼是一段Android事件監聽代碼:
scan_bt.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub } }); history_bt.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub } });
這段代碼爲兩個按鈕設置監聽器,這裏面就使用了匿名內部類。具體位置是這段:
new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub } }
代碼中須要給按鈕設置監聽器對象,使用匿名內部類可以在實現父類或者接口中的方法狀況下同時產生一個相應的對象,可是前提是這個父類或者接口必須先存在才能這樣使用。固然像下面這種寫法也是能夠的,跟上面使用匿名內部類達到效果相同:
private void setListener() { scan_bt.setOnClickListener(new Listener1()); history_bt.setOnClickListener(new Listener2()); } class Listener1 implements View.OnClickListener{ @Override public void onClick(View v) { // TODO Auto-generated method stub } } class Listener2 implements View.OnClickListener{ @Override public void onClick(View v) { // TODO Auto-generated method stub } }
這種寫法雖然能達到同樣的效果,可是既冗長又難以維護,因此通常使用匿名內部類的方法來編寫事件監聽代碼。一樣的,匿名內部類也是不能有訪問修飾符和static修飾符的。
匿名內部類是惟一一種沒有構造器的類。正由於其沒有構造器,因此匿名內部類的使用範圍很是有限,大部分匿名內部類用於接口回調。匿名內部類在編譯的時候由系統自動起名爲Outter$1.class。通常來講,匿名內部類用於繼承其餘類或是實現接口,並不須要增長額外的方法,只是對繼承方法的實現或是重寫。