嵌套類是指被定義在另外一個類的內部的類。java
嵌套類存在的目的是:只是爲它的外部類提供服務;多線程
outer.java裏面定義了一個內部類inner,運行時,一旦編譯成功,就會生成兩個徹底不一樣的.class文件,分別是outer.class和outer$inner.class。ide
嵌套類分爲四種:靜態成員類,非靜態成員類(成員內部類),匿名類,局部類。測試
內部類:非靜態成員類(成員內部類),匿名類,局部類。spa
1.靜態內部類
1 public class Outer { 2 3 public static String name = "Joe"; 4 private String password = "0806"; 5 6 //靜態內部類 7 public static class inner{ 8 public static void print1(){ 9 System.out.println(name); 10 //調用外部類的靜態方法 11 outerPrint(); 12 } 13 public void print2(){ 14 System.out.println(name); 15 } 16 } 17 18 public static void outerPrint(){ 19 System.out.println("Outer static method!"); 20 } 21 22 public static void main(String[] args){ 23 //靜態內部類的靜態方法調用 24 Outer.inner.print1(); 25 //靜態內部類的非靜態方法調用 26 Outer.inner inner = new Outer.inner(); 27 inner.print2(); 28 } 29 }
輸出結果:線程
Joe
Outer static method!
Joecode
經過這個例子能夠看出:對象
♥ 靜態內部類中能夠有靜態方法,也能夠有非靜態方法;blog
♥ 靜態內部類只能訪問其外圍類的靜態成員和靜態方法;繼承
♥ 和普通的類同樣,要訪問靜態內部類的靜態方法,能夠直接「.」出來,不須要一個實例;
♥ 要訪問靜態內部類的非靜態方法,必須拿到一個靜態內部類的實例對象;
♥ 實例化靜態內部類:外圍類.內部類 xxx = new 外圍類.內部類();
能夠把靜態內部類看做普通的類,只是碰巧被聲明在另外一個類的內部而已;若是靜態內部類被聲明爲私有的,那麼它就只能在外圍類的內部才能夠訪問。
非靜態成員類(成員內部類)
成員內部類是最多見的內部類,就是在外部類的基礎上按照通常定義類的方式定義類,舉個例子:
1 public class Outer { 2 3 public static String name = "Joe"; 4 private String password = "0806"; 5 6 //私有成員內部類 7 private class PrivateInner{ 8 public void print1(){ 9 System.out.println("private " + name); 10 System.out.println("public " + password); 11 //調用外部類的靜態方法 12 outerPrint(); 13 } 14 } 15 //公有的成員內部類 16 public class PublicInner{ 17 public void print2(){ 18 String password = "0810"; 19 System.out.println("public " + name); 20 System.out.println("public " + password); 21 //調用外部類的靜態方法 22 outerPrint(); 23 } 24 } 25 public static void outerPrint(){ 26 System.out.println("Outer static method!"); 27 } 28 29 public static void main(String[] args){ 30 Outer outer = new Outer(); 31 Outer.outerPrint(); 32 //實例化私有成員內部類 33 Outer.PrivateInner privateInner = outer.new PrivateInner(); 34 privateInner.print1(); 35 //實例化公有成員內部類 36 Outer.PublicInner publicInner = outer.new PublicInner(); 37 publicInner.print2(); 38 } 39 }
輸出結果:
Outer static method!
private Joe
public 0806
Outer static method!
public Joe
public 0810
Outer static method!
經過這個例子能夠看出:
♥ 成員內部類是依附其外圍類而存在的,若是要產生一個成員內部類,必須有一個其外圍類的實例;
♥ 成員內部類不能夠定義靜態方法和靜態屬性;
♥ 聲明爲private的成員內部類,只對其外圍類可見;聲明爲public的成員內部類,其餘非外圍類對其可見;
♥ 成員內部類能夠訪問外圍類的私有屬性,若是成員內部類的屬性和其外圍類的屬性重名,則以成員內部類的屬性值爲準;
♥ 實例化成員內部類:外圍類.內部類 xxx = 外圍類.new 內部類();
匿名內部類
在多線程的模塊中代碼,大量使用了匿名內部類,以下:
1 public class Outer { 2 //匿名接口 3 interface Inner{ 4 int getNumber(); 5 } 6 //使用匿名接口 7 public Inner getInner(final int num,String str){ 8 return new Inner() { 9 @Override 10 public int getNumber() { 11 System.out.println(str); 12 return num; 13 } 14 }; /* 注意:分號不能省 */ 15 } 16 //測試 17 public static void main(String[] args){ 18 Outer outer = new Outer(); 19 Inner inner = outer.getInner(4,"nihao"); 20 System.out.println(inner.getNumber()); 21 } 22 }
輸出結果:
nihao 4
經過這個例子能夠看出:
❤ 匿名內部類沒有修飾符;
❤ 當所在方法的形參須要被匿名內部類使用時,該形參必須爲final,由於:內部類在編譯時會生成一個獨立的.class文件,改文件並不在它的外圍類中,內部類將傳過來的參數經過本身的構造器備份到了本身的內部,這樣本身內部方法的調用其實是本身的屬性,而不是外圍類方法的參數;簡單理解就是:拷貝引用,爲了不引用值發生改變,例如被外圍類的方法修改等,而致使內部類獲得的值不一致,因而用final修飾讓該引用不可變;
❤ 匿名內部類沒有構造方法,由於它連名字都沒有;
❤ new 匿名內部類;這個類必須先存在;
局部內部類
局部內部類:是指內部類定義在方法和做用域內。
看個例子:
1 public class Outer { 2 private void internalTracking(boolean b) { 3 if (b) { 4 //局部內部類 5 class TrackingSlip { 6 private String id; 7 TrackingSlip(String s) { 8 id = s; 9 } 10 String getSlip() { 11 return id; 12 } 13 } 14 TrackingSlip ts = new TrackingSlip("slip"); 15 String s = ts.getSlip(); 16 } 17 } 18 19 public void track() { 20 //調用方法(含有局部內部類) 21 internalTracking(true); 22 System.out.println("......."); 23 } 24 25 public static void main(String[] args) { 26 Outer p = new Outer(); 27 p.track(); 28 } 29 }
局部內部類也會像其餘類同樣編譯,只是做用域不一樣而已,只有在該方法或者做用域內才能用,超出做用域或者方法就不可引用。
❤ 局部內部類沒有訪問修飾符;
❤ 局部內部類要訪問外圍類的對象或者變量,那麼這個變量或者對象必須是final修飾的;
內部類的好處
❤ Java運行實現多個接口,但不容許繼承多個類,使用內部類能夠解決Java不容許多個繼承的問題。在一個類的內部定義一個內部類,讓這個內部類繼承某個原有的類,而這個內部類又能夠訪問外圍類的屬性和方法,這樣就至關於多個繼承了;
❤ 有效的對外隱藏了本身,增長了本身的私密性;
❤ 使用內部類可讓類與類之間的聯繫更加緊密;
❤ 有些類知道只會在某個地方使用只使用一次,爲這種類建立一個外部類顯然沒有必要,因此這種就寫個內部類用用就能夠了;