內部類一共分爲:成員內部類,局部內部類,靜態嵌套類,匿名內部類。java
最普通的內部類多線程
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(); } }
成員內部類,就是做爲外部類的成員,能夠直接使用外部類的全部成員和方法,即便是private的。雖然成員內部類能夠無條件地訪問外部類的成員,而外部類想訪問成員內部類的成員卻不是這麼爲所欲爲了。在外部類中若是要訪問成員內部類的成員,必須先建立一個成員內部類的對象,再經過指向這個對象的引用來訪問this
要注意的是,成員內部類不能含有static的變量和方法。由於成員內部類須要先建立了外部類,才能建立它本身的。可是將其加一個final,就能夠了,因此還須要追究一下final static和static的區別。spa
局部內部類是定義在一個方法或者一個做用域裏面的類,它和成員內部類的區別在於局部內部類的訪問僅限於方法內或者該做用域內。線程
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); } }
本例中咱們將內部類移到了外部類的方法中,而後在外部類的方法中再生成一個內部類對象去調用內部類方法。若是此時咱們須要往外部類的方法中傳入參數,那麼外部類的方法形參必須使用final定義。code
換句話說,在方法中定義的內部類只能訪問方法中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(x); } } new Inner().inPrint(); } } } public class test1 { public static void main(String[] args) { Outter out = new Outter(); out.Print(true); } }
又叫靜態局部類、嵌套內部類,就是修飾爲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(); } }
能夠看到,若是用static 將內部內靜態化,那麼內部類就只能訪問外部類的靜態成員變量,具備侷限性。接口
其次,由於內部類被靜態化,所以Outter.Inner能夠當作一個總體看,能夠直接new 出內部類的對象(經過類名訪問static,生不生成外部類對象都不要緊)生命週期
匿名內部類也就是沒有名字的內部類
正由於沒有名字,因此匿名內部類只能使用一次,它一般用來簡化代碼編寫
但使用匿名內部類還有個前提條件:必須繼承一個父類或實現一個接口
咱們先來看一個例子,不使用匿名內部類實現方法
abstract class Person { public abstract void eat(); } class Child extends Person { public void eat() { System.out.println("eat something"); } } public class Demo { public static void main(String[] args) { Person p = new Child(); p.eat(); } }
假設Child類只用一次,那麼這樣作成一個類就是太浪費了。因此這個時候咱們用匿名內部類實現就比較好:
abstract class Person { public abstract void eat(); } public class Demo { public static void main(String[] args) { Person p = new Person() { public void eat() { System.out.println("eat something"); } }; p.eat(); } }
在接口上實現內部類:
interface Person { public void eat(); } public class Demo { public static void main(String[] args) { Person p = new Person() { public void eat() { System.out.println("eat something"); } }; p.eat(); } }
由上面的例子能夠看出,只要一個類是抽象的或是一個接口,那麼其子類中的方法均可以使用匿名內部類來實現
最經常使用的狀況就是在多線程的實現上,由於要實現多線程必須繼承Thread類或是繼承Runnable接口