1. 程式人生 > >內部類(嵌套類)

內部類(嵌套類)

.class 方法調用 方法的參數 分別是 外部 必須 tin 一個 override

嵌套類是指被定義在另一個類的內部的類。

嵌套類存在的目的是:只是為它的外部類提供服務;

outer.java裏面定義了一個內部類inner,運行時,一旦編譯成功,就會生成兩個完全不同的.class文件,分別是outer.class和outer$inner.class。所以嵌套類的名字完全可以和它的外部類名字相同。

嵌套類分為四種:靜態成員類,非靜態成員類(成員內部類),匿名類,局部類。

內部類:非靜態成員類(成員內部類),匿名類,局部類。

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!
Joe

通過這個例子可以看出:

  ? 靜態內部類中可以有靜態方法,也可以有非靜態方法;

  ? 靜態內部類只能訪問其外圍類的靜態成員和靜態方法;

  ? 和普通的類一樣,要訪問靜態內部類的靜態方法,可以直接“.”出來,不需要一個實例;

  ? 要訪問靜態內部類的非靜態方法,必須拿到一個靜態內部類的實例對象;

  ? 實例化靜態內部類:外圍類.內部類 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不允許多個繼承的問題。在一個類的內部定義一個內部類,讓這個內部類繼承某個原有的類,而這個內部類又可以訪問外圍類的屬性和方法,這樣就相當於多個繼承了;

  ? 有效的對外隱藏了自己,增加了自己的私密性;

  ? 使用內部類可以讓類與類之間的聯系更加緊密;

  ? 有些類知道只會在某個地方使用只使用一次,為這種類創建一個外部類顯然沒有必要,所以這種就寫個內部類用用就可以了;

內部類(嵌套類)