內部類(inner class)的簡單介紹

本文主要介紹內部類(inner class)的一些基本應用,將從內部類的分類角度,首先對每個具體內部類進行介紹。主要包括普通的內部類【common inner class】、局部內部類[local inner class]、嵌套內部類【nested innner class】、匿名內部類【anonymous inner class】、而後比較一下局部內部類[local inner class]和匿名內部類【anonymous inner class ]的區別,進而知道在具體狀況下該選擇內部類,即到底用local inner class仍是anonymous inner class。最後介紹內部類的應用java

一:首先對每個具體內部類進行介紹ide

1.普通的內部類【common inner class】函數

定義:在一個類裏面直接定義一個類:this

一些詳細狀況看代碼:spa

 1 package com.qls.comonInnerClass;
 2 
 3 public class A {
 4     /**
 5      * 從B C D E 這四個普通內部類中能夠看出類前面的修飾符能夠是
 6      * private  protected default(也就是什麼修飾符沒有的D) public.  而在局部內部類中修飾類的只能是:
 7      * abstract 或final 或者什麼修飾符都沒有。
 8      * 注意的問題以下:
 9      * 1.一般狀況下:外部類會有一個返回內部類引用的一個方法如getB()這個方法。
10      * 2.如何在內部類中用this指代外部類引用?【答:外部類名.this 參考第19行代碼。】
11      * 以及如何建立內部類的一個實例?【答:x.new B() 其中x是外部類的一個實例,B爲一個內部類。
12      * 如果直接寫new B()會報錯。參考第3八、39兩行代碼。】
13      * 上述兩個注意點對其餘的內部類也適用。
14      * @author 秦林森
15      *
16      */
17     private  class B {
18         public A outer(){
19             return A.this;//A.this是指代A的一個引用。
20         }
21     }
22     protected class C{
23         
24     }
25     class D{
26         
27     }
28     public class E{
29         
30     }
31     /**
32      * 返回內部類的引用:
33      */
34     B getB(){
35         return new B();
36     }
37     public static void main(String[] args) {
38         A a = new A();
39         B b = a.new B();
40     }
41 }

局部內部類【local innner class】code

定義:把類定義在方法裏面,或者是方法中的某一個區域中。對象

代碼以下:blog

 1 package com.qls.localInnerClass2;
 2 /**
 3  * 定義:the creation of an entire class within the scope of a method,or Nesting a class within 
 4  * a scope of a method.
 5  * This is called a local inner class.
 6  * 注意狀況以下:
 7  * 1.局部內部類【local inner class】若是想要修飾的話,只有abstract 和final能夠,
 8  * 其他的如(public protected)等都不能夠。
 9  * 2.在局部內部類中只能訪問包含該內部類的範圍(enclosing scope)的final變量。若不是則會報錯。
10  * 
11  * @author 秦林森
12  *
13  */
14 public class A {
15     public void ouyangfeng(){
16         //把類D定義在方法ouyangfeng()的某個區域中。
17         if(3>2){
18             class D{
19                 
20             }
21         }
22         final class B{
23             
24         }
25     }
26     
27     public void  sixi(final String s){
28         int e=1;
29         final int c=8;
30         class C{
31             /**
32              * 在局部內部類或者匿名內部類中只能訪問包含該內部類的範圍(enclosing scope)的final變量。
33              * 若不是則會報錯。
34              * 如int f=e;編譯器報錯。
35              */
36             String str=s;
37             int d=c;
38 //            int f=e;//編譯器報錯。
39         }
40     }
41     public static void main(String[] args) {
42         // TODO Auto-generated method stub
43 
44     }
45 
46 }

匿名內部類:沒有名字的內部類。繼承

下面的代碼介紹瞭如下的內容:接口

1.匿名內部類實現一個接口,

2.匿名內部類實現一個沒有默認構造方法的抽象類

3.匿名內部類和局部內部類同樣把參數定義成final,完成字段初始化

4.匿名內部類用普通代碼塊{}完成初始化,彌補了匿名內部類沒有構造方法的缺陷。

代碼以下:

package com.qls.anonymouseInnerClass;
/**
 * 匿名內部類(anonymous inner class)通常用在return 語句中。
 * 注意狀況以下:
 * 匿名內部類因爲沒有名字,天然而然也就沒有構造方法,其餘三種內部類都有構造方法。
 * 沒有構造方法怎麼給對象賦值進行初始化呢?【答:用普通的代碼塊{},在這個代碼塊裏面實行初始化。】
 * @author 秦林森
 *
 */
interface B{
    void ouyangfeng();
}
abstract class C{
    private int i;
    public C(int i) {
        this.i=i;
    }
    public abstract int value();
    
}
public class A {
    public B getB(){
        //new B(){};就是匿名內部類:用默認的構造方法
        return new B() {
            
            @Override
            public void ouyangfeng() {
                // TODO Auto-generated method stub
                System.out.println("ouyangfeng is chief village of sixi ");
            }
        };
    }
    public C getC(final int i){
        //匿名內部類用一個帶參數的構造方法
        return new C(i) {
            //用普通代碼塊實現初始化:
            {
                //這裏寫兩個輸出語句做爲演示。
                System.out.println("泗溪");
                System.out.println("ouyangfeng");
                System.out.println(value());//輸出value的值
            }
            @Override
            public int value() {
                // TODO Auto-generated method stub
                return i;//從這裏能夠看出要想引用i,必須把i定義成final。這和局部內部類同樣。
            }
        };
        
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new A().getC(4);//輸出泗溪、ouyangfeng、4
        
    }

}

 嵌套內部類:

 1 package com.qls.nestedClass;
 2 /**
 3  * 若是你不想讓內部類的對象和外部類的對象有如何聯繫的話,你就能夠把內部類定義成static
 4  * 嵌套內部類(Nested inner class)的定義:類中關鍵詞static修飾的內部類。
 5  * 注意狀況以下:
 6  * 1.在嵌套內部類中不能訪問外部類的非靜態變量。
 7  * 2.建立內部類變量時,你不想經過建立外部類變量才能建立內部類變量時,你能夠把這個內部類定義成static
 8  * 即嵌套內部類。
 9  * 3.在接口interface中定義的內部類默認都是public static 的,因此在接口中的內部類必是嵌套內部類。
10  * @author 秦林森
11  *
12  */
13 interface D{
14     void hello();
15     class Test implements D{
16 
17         @Override
18         public void hello() {
19             // TODO Auto-generated method stub
20             System.out.println("hello");
21         }
22         public static void main(String[] args) {
23             /**
24              * 因爲Test類默認是public static 的,因此建立Test對象時,不須要經過外部類D,
25              * 因此直接new Test()便可建立Test類中的一個對象。
26              * 話又說回來了,若是在接口中的類不是public static 的那麼這個內部類也就是普通的內部類
27              * 在建立Test的對象時,也就須要外部類的對象。關鍵D是接口,你怎麼new 呢?
28              * 因此在的類只能是static 的。
29              */
30             new Test().hello();//輸出hello
31         }
32     }
33 }
34 public class A {
35     int a=9;
36     public static  class B{
37 //        int b=a;編譯報錯
38          void f(){
39             System.out.println("f()");
40         }
41     }
42     public static void main(String[] args) {
43         /**
44          * 從這裏你看到了,能夠對B直接new ,訪問B中的函數f().
45          * 可是若是B沒有static這個關鍵字,即B是普通內部類時,必須這樣才能訪問到f()
46          * new A().new B().f();
47          */
48         new B().f();
49     }
50 }

 二:比較一下局部內部類[local inner class]和匿名內部類【anonymous inner class ]的區別

1.匿名內部類沒有構造犯法,二局部內部類有構造方法。

2.若是在一個外部類有兩個或兩個以上的方法,返回的都是某個接口或者抽象類的引用,建議把寫一個局部內部類。若寫成匿名內部類時,代碼會顯得特別冗長。反之若是一個時,建議用匿名內部類。

代碼以下:

 1 package com.qls.anonymouseInnerClass;
 2 interface Six{
 3     void six();
 4 }
 5 public class Ouyangfeng {
 6     private class SixTest implements Six{
 7 
 8         @Override
 9         public void six() {
10             // TODO Auto-generated method stub
11             
12         }
13         
14     }
15     public Six f(){
16         return new SixTest();
17     }
18     public Six g(){
19         return new SixTest();
20     }
21 }

三:內部類的應用:

用內部類實現java的多重繼承。

 1 package com.qls.anonymouseInnerClass;
 2 class D{
 3     
 4 }
 5 abstract class E{
 6     
 7 }
 8 class F extends D{
 9     //這是實現多重繼承的核心代碼。這裏是用一個匿名內部類實現
10     E makeE(){
11         return new E() {
12         };
13     }
14 }
15 public class MultipleInherit {
16     public static void takesD(D d){
17         
18     }
19     public static void takesE(E d){
20         
21     }
22     public static void main(String[] args) {
23         // TODO Auto-generated method stub
24         F d = new F();
25         takesD(d);
26         takesE(d.makeE());
27     }
28 
29 }

最後簡要介紹一下讓一個類繼承另外一個類中的內部類?以及怎麼讓一個類中的內部類繼承另外一個類的內部類呢?

首先是:讓一個類繼承另外一個類中的內部類

 代碼以下:

 1 package com.qls.anonymouseInnerClass;
 2 
 3 import com.qls.anonymouseInnerClass.WithInner.Inner;
 4 
 5 class WithInner{
 6     class Inner{
 7         private int a;
 8         public Inner(int a) {
 9             this.a=a;
10         }
11         public Inner() {
12             // TODO Auto-generated constructor stub
13         }
14     }
15 }
16 public class InheritInner extends Inner{
17     public InheritInner(WithInner withInner) {
18         // TODO Auto-generated constructor stub
19         /**
20          * 這句話必需要寫。不然編譯器會報錯。即:外部類的一個對象.super().
21          * 這裏的super(),比奧斯Inner的一個默認構造方法。
22          * 若是Inner中好比有這樣一個構造方法:public Inner(int a) 
23          * 你如今也能夠寫成:把withInner.super();改成withInner.super(1);編譯器是不會報錯的。
24          * 若是沒有默認構造方法public Inner() 則這題必須寫成:withInner.super(1);的形式。
25          */
26         
27         withInner.super();
28     }
29     public static void main(String[] args) {
30         // TODO Auto-generated method stub
31         WithInner withInner = new WithInner();
32         InheritInner inheritInner = new InheritInner(withInner);
33     }
34 
35 }

 讓一個類中的內部類繼承另外一個類的內部類

代碼以下:

 1 package com.qls.anonymouseInnerClass;
 2 /**
 3  * 朱元璋家住鳳陽,劉伯溫家住青田
 4  * @author 秦林森
 5  *
 6  */
 7 class ZhuYuanZhang{
 8     class FengYang{
 9         private String location;
10 
11         public FengYang(String location) {
12             this.location = location;
13         }
14         
15     }
16 }
17 class LiuBoWei{
18     class QingTian extends ZhuYuanZhang.FengYang{
19         private String location;
20         public QingTian(ZhuYuanZhang zhuYuanZhang, String location) {
21             zhuYuanZhang.super(location);//這句話必需要寫。或者會報錯,
22             this.location=location;
23         }
24         public void accurate(){
25             System.out.println("一統江山劉伯溫 ,家在"+location);
26         }
27     }
28 }
29 public class Test {
30 
31     public static void main(String[] args) {
32         // TODO Auto-generated method stub
33         new LiuBoWei().new QingTian(new ZhuYuanZhang(), "青田").accurate();
34     }
35 
36 }/*Output:
37 一統江山劉伯溫 ,家在青田*///:~
相關文章
相關標籤/搜索