qileilove

          blog已經(jīng)轉(zhuǎn)移至github,大家請?jiān)L問 http://qaseven.github.io/

          Java核心類庫:內(nèi)部類那點(diǎn)事兒

            內(nèi)部類:定義在類的內(nèi)部的類

            為什么需要內(nèi)部類?

            ● 典型的情況是,內(nèi)部類繼承自某個(gè)類或?qū)崿F(xiàn)某個(gè)接口,內(nèi)部類的代碼操作創(chuàng)建其的外圍類的對象。所以你可以認(rèn)為內(nèi)部類提供了某種進(jìn)入其外圍類的窗口。

            ● java中的內(nèi)部類和接口加在一起,可以實(shí)現(xiàn)多繼承。

            ● 可以使某些編碼根簡潔。

            ● 隱藏你不想讓別人知道的操作。

            使用內(nèi)部類最吸引人的原因是:

             每個(gè)內(nèi)部類都能獨(dú)立地繼承自一個(gè)(接口的)實(shí)現(xiàn),所以無論外圍類是否已經(jīng)繼承了某個(gè)(接口的)實(shí)現(xiàn),對于內(nèi)部類都沒有影響。如果沒有內(nèi)部類提供的可以繼 承多個(gè)具體的或抽象的類的能力,一些設(shè)計(jì)與編程問題就很難解決。從這個(gè)角度看,內(nèi)部類使得多重繼承的解決方案變得完整。接口解決了部分問題,而內(nèi)部類有效 地實(shí)現(xiàn)了“多重繼承”。

            內(nèi)部類分為: 成員內(nèi)部類、靜態(tài)嵌套類、方法內(nèi)部類、匿名內(nèi)部類。

            特點(diǎn):

            一、內(nèi)部類仍然是一個(gè)獨(dú)立的類,在編譯之后內(nèi)部類會(huì)被編譯成獨(dú)立的.class文件,但是前面冠以外部類的類命和$符號。

            二、內(nèi)部類可以直接或利用引用訪問外部類的屬性和方法,包括私有屬性和方法(但靜態(tài)內(nèi)部類不能訪問外部類的非靜態(tài)成員變量和方法)。內(nèi)部類所訪問的外部屬性的值由構(gòu)造時(shí)的外部類對象決定。

            三、而外部類要訪問內(nèi)部類的成員,則只能通過引用的方式進(jìn)行,可問內(nèi)部類所有成員

            四、訪問機(jī)制:

          1. System.out.println(this.x);或System.out.println(x);//內(nèi)部類訪問內(nèi)部類的成員變量或成員方法可用此方法。 

          2. System.out.println(OuterClass.this.x);//內(nèi)部類訪問外部類的同名變量時(shí)可用此方法,如果沒有同名可用System.out.println(x);

            五、內(nèi)部類可以使用任意的范圍限定:public/private/protected class InnerClass,且嚴(yán)格按照這幾種訪問權(quán)限來控制內(nèi)部類能使用的范圍。普通類的范圍限定只可以是public或者不加。

            六、內(nèi)部類的命名不允許與外部類 重名,內(nèi)部類可以繼承同級的內(nèi)部類,也可繼承其它類(除內(nèi)部類和外部類)。

            七、內(nèi)部類可以定義為接口,并且可以定義另外一個(gè)類來實(shí)現(xiàn)它

            八、內(nèi)部類可以定義為抽象類,可以定義另外一個(gè)內(nèi)部類繼承它

            九、內(nèi)部類使用static修飾,自動(dòng)升級為頂級類,外部類不可以用static修飾,用OuterClass.InnerClass inner=new OuterClass.InnerClass();創(chuàng)建實(shí)例。內(nèi)部類還可定義為final.

            十、內(nèi)部類可以再定義內(nèi)部類(基本不用)

            十一、方法內(nèi)的內(nèi)部類:

            方法內(nèi)的內(nèi)部類不能加范圍限定(protected public private)

            方法內(nèi)的內(nèi)部類不能加static修飾符

            方法內(nèi)的內(nèi)部類只能在方法內(nèi)構(gòu)建其實(shí)例

            方法內(nèi)的內(nèi)部類如果訪問方法局部變量,則此局部變量必須使用final修飾

            1)靜態(tài)內(nèi)部類(靜態(tài)嵌套類)

            從技術(shù)上講,靜態(tài)嵌套類不屬于內(nèi)部類。因?yàn)閮?nèi)部類與外部類共享一種特殊關(guān)系,更確切地說是對實(shí)例的共享關(guān)系。而靜態(tài)嵌套類則沒有上述關(guān)系。它只是位置在另一個(gè)類的內(nèi)部,因此也被稱為頂級嵌套類。

            靜態(tài)的含義是該內(nèi)部類可以像其他靜態(tài)成員一樣,沒有外部類對象時(shí),也能夠訪問它。靜態(tài)嵌套類不能訪問外部類的成員和方法。

           語法

          1. package com.tarena.day13;  
          2.  
          3. import com.tarena.day13.Foo.Koo;  
          4. /**  
          5.  * 靜態(tài)類內(nèi)部語法演示  
          6.  */ 
          7. public class StaticInner {  
          8.  public static void main(String[] args) {  
          9.   Koo koo = new Koo();  
          10.   System.out.println(koo.add());//4  
          11.  }  
          12.  
          13. }  
          14. class Foo{  
          15.  int a = 1;  
          16.  static int b = 3;  
          17.  /** 靜態(tài)內(nèi)部類,作用域類似于靜態(tài)變量,屬于類的 */ 
          18.  static class Koo{  
          19.   public int add(){  
          20.    //a ,不能訪問a  
          21.    return b+1;  
          22.   }  
          23.  }  
          24. }

            2)成員內(nèi)部類

            * 1 成員內(nèi)部類必須利用外部類實(shí)例創(chuàng)建

            * 2 成員內(nèi)部類可以共享外部類的實(shí)例變量

          1. import com.tarena.day13.inn.Goo.Moo;  
          2.  
          3. public class InnerClassDemo {  
          4.  public static void main(String[] args) {  
          5.   //Moo moo = new Moo(); //編譯錯(cuò)誤,必須創(chuàng)建Goo的實(shí)例  
          6.   Goo goo = new Goo();  
          7.   Moo moo = goo.new Moo();//利用goo實(shí)例創(chuàng)建Moo實(shí)例  
          8.   Moo moo1 = goo.new Moo();  
          9.   //moo和moo1共享同一個(gè)goo實(shí)例的實(shí)例變量  
          10.   System.out.println(moo.add());//2  
          11.   System.out.println(moo1.add());//2  
          12.   Goo goo1 = new Goo();  
          13.   goo1.a = 8;  
          14.   Moo m1 = goo1.new Moo();  
          15.   Moo m2 = goo1.new Moo();  
          16.   System.out.println(m1.add());//9  
          17.   System.out.println(m2.add());//9  
          18.     
          19.  }  
          20. }  
          21. class Goo{  
          22.  int a = 1;  
          23.  /**成員內(nèi)部類*/ 
          24.  class Moo{  
          25.   public int add(){  
          26.    return a+1;  
          27.   }  
          28.  }  
          29. }

            3)局部內(nèi)部類(方法內(nèi)部類)

            (1)方法內(nèi)部類只能在定義該內(nèi)部類的方法內(nèi)實(shí)例化,不可以在此方法外對其實(shí)例化。

            (2)方法內(nèi)部類對象不能使用該內(nèi)部類所在方法的非final局部變量。

            因?yàn)榉椒ǖ木植孔兞课挥跅I希淮嬖谟谠摲椒ǖ纳趦?nèi)。當(dāng)一個(gè)方法結(jié)束,其棧結(jié)構(gòu)被刪除,局部變量成為歷史。但是該方法結(jié)束之后,在方法內(nèi)創(chuàng) 建的內(nèi)部類對象可能仍然存在于堆中!例如,如果對它的引用被傳遞到其他某些代碼,并存儲(chǔ)在一個(gè)成員變量內(nèi)。正因?yàn)椴荒鼙WC局部變量的存活期和方法內(nèi)部類對 象的一樣長,所以內(nèi)部類對象不能使用它們。用法

          1. package com.tarena.day13.inn;  
          2.  
          3. import java.util.Comparator;  
          4.  
          5. /**  
          6.  * 局部內(nèi)部類  
          7.  */ 
          8. public class LocalInnerClassDemo {  
          9.  public static void main(String[] args) {  
          10.   int a = 5;  
          11.   final int b = 5;  
          12.   //局部內(nèi)部類,定義在方法內(nèi)部,作用域類似于局部變量  
          13.   //僅僅在方法內(nèi)部可見  
          14.   //在局部內(nèi)部類中可以訪問方法中的局部final變量  
          15.   class Foo{  
          16.    public int add(){  
          17.     return  b;//正確  
          18.     //return a;//編譯錯(cuò)誤  
          19.    }  
          20.   }  
          21.     
          22.   Foo foo = new Foo();  
          23.   //臨時(shí)的自定義比較規(guī)則  
          24.   class ByLength implements Comparator<String>{  
          25.    public int compare(String o1,String o2){  
          26.     return o1.length()-o2.length();  
          27.    }  
          28.   }  
          29.  }  
          30.  
          31. }

            4)匿名內(nèi)部類

            顧名思義,沒有名字的內(nèi)部類。表面上看起來它們似乎有名字,實(shí)際那不是它們的名字。

            匿名內(nèi)部類就是沒有名字的內(nèi)部類。什么情況下需要使用匿名內(nèi)部類?如果滿足下面的一些條件,使用匿名內(nèi)部類是比較合適的:

            只用到類的一個(gè)實(shí)例。

            ● 類在定義后馬上用到。

            ● 類非常小(SUN推薦是在4行代碼以下)

            ● 給類命名并不會(huì)導(dǎo)致你的代碼更容易被理解

            在使用匿名內(nèi)部類時(shí),要記住以下幾個(gè)原則:

            ● 匿名內(nèi)部類不能有構(gòu)造方法。

            ● 匿名內(nèi)部類不能定義任何靜態(tài)成員、方法和類。

            ● 匿名內(nèi)部類不能是public,protected,private,static。

            ● 只能創(chuàng)建匿名內(nèi)部類的一個(gè)實(shí)例。

            ● 一個(gè)匿名內(nèi)部類一定是在new的后面,用其隱含實(shí)現(xiàn)一個(gè)接口或?qū)崿F(xiàn)一個(gè)類。

            ● 因匿名內(nèi)部類為局部內(nèi)部類,所以局部內(nèi)部類的所有限制都對其生效。

            A、繼承式的匿名內(nèi)部類和接口式的匿名內(nèi)部類。

          1. import java.util.Arrays;  
          2. import java.util.Comparator;  
          3.  
          4. /**匿名內(nèi)部類 語法*/ 
          5. public class AnnInnerClass {  
          6.  
          7.  public static void main(String[] args) {  
          8.   // TODO Auto-generated method stub  
          9.   Yoo yoo = new Yoo();//創(chuàng)建Yoo的實(shí)例  
          10.   Yoo y1 = new Yoo(){};  
          11.   //new Yoo(){}創(chuàng)建匿名類實(shí)例  
          12.   //匿名類new Yoo(){}是繼承Yoo類,并且同時(shí)創(chuàng)建了對象  
          13.   //new Yoo(){}是Yoo的子類型,其中{}是類體(class Body)  
          14.   //類體中可以定義任何類內(nèi)的語法,如:屬性,方法,方法重載,方法覆蓋,等  
          15.   //子類型沒有名字,所以叫匿名類!  
          16.   Yoo y2 = new Yoo(){  
          17.    public String toString(){//方法重寫(覆蓋)  
          18.     return "y2"; //y2是子類的實(shí)例  
          19.    }  
          20.   };  
          21.   System.out.println(y2);//"y2",調(diào)用了匿名類對象toString()  
          22.   //匿名內(nèi)部類可以繼承/實(shí)現(xiàn) 于 類,抽象類,接口等  
          23.   //按照繼承的語法,子類型必須實(shí)現(xiàn)所有的抽象方法  
          24.     
          25.   //Xoo x = new Xoo(){};//編譯錯(cuò)誤,沒有實(shí)現(xiàn)方法  
          26.   final int b = 5;  
          27.   Xoo xoo = new Xoo(){ //是實(shí)現(xiàn)接口,并且創(chuàng)建匿名類實(shí)例,不是創(chuàng)建接口對象  
          28.    public int add(int a){//實(shí)現(xiàn)接口中的抽象方法  
          29.     return a+b; //要訪問局部變量b,只能訪問final變量  
          30.    }  
          31.   };  
          32.   System.out.println(xoo.add(5));//10,調(diào)用對象的方法  
          33.   //Comparator接口也可以使用匿名類的方式  
          34.   Comparator<String> byLength = new Comparator<String>(){  
          35.    public int compare(String o1,String o2){  
          36.     return o1.length()-o2.length();  
          37.       
          38.    }  
          39.   };  
          40.   String[] names = {"Andy","Tom","Jerry"};  
          41.   Arrays.sort(names,byLength);  
          42.   System.out.println(Arrays.toString(names));  
          43.   //也可以這樣寫,工作中常用  
          44.   Arrays.sort(names,new Comparator<String>(){  
          45.    public int compare(String o1,String o2){  
          46.     return o1.length()-o2.length();  
          47.    }  
          48.   });  
          49.  }  
          50.  
          51. }
           接口式的匿名內(nèi)部類是實(shí)現(xiàn)了一個(gè)接口的匿名類。而且只能實(shí)現(xiàn)一個(gè)接口。

            B. 參數(shù)式的匿名內(nèi)部類。

          1. class Bar{   
          2.     void doStuff(Foo f){  
          3.      }   
          4. }   
          5. interface Foo{   
          6.     void foo();   
          7. }   
          8. class Test{    
          9.  static void go(){    
          10.      Bar b = new Bar();    
          11.      b.doStuff(new Foo(){    
          12.          public void foo(){    
          13.              System.out.println("foofy");    
          14.          }   
          15.       });   
          16.  }   
          17. }

            構(gòu)造內(nèi)部類對象的方法有:

            1、內(nèi)部類在自己所處的外部類的靜態(tài)方法內(nèi)構(gòu)建對象或在另一個(gè)類里構(gòu)造對象時(shí)應(yīng)用如下形式:

            (1)

          1. OuterClass out = new OuterClass();  
          2. OuterClass.InnerClass in = out.new InnerClass();

            (2)

          OuterClass.InnerClass in=new OuterClass().new InnerClass();

            其中OuterClass是外部類,InnerClass是內(nèi)部類。

            2、內(nèi)部類在它所在的外部類的非靜態(tài)方法里或定義為外部類的成員變量時(shí),則可用以下方式來構(gòu)造對象:

          InnerClass in = new InnerClass();

            3、如果內(nèi)部類為靜態(tài)類,則可用如下形式來構(gòu)造函數(shù):

          OuterClass.InnerClass in = new OuterClass.InnerClass();

            無需再利用外部類的對象來來構(gòu)造內(nèi)部類對象,如果靜態(tài)內(nèi)部類需要在靜態(tài)方法或其它類中構(gòu)造對象就必須用上面的方式來初始化。


          posted on 2012-04-19 09:59 順其自然EVO 閱讀(161) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          <2012年4月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 樟树市| 凤翔县| 大港区| 临沭县| 百色市| 兴隆县| 盐边县| 长岭县| 无为县| 廊坊市| 三都| 赤水市| 桓仁| 潜山县| 原平市| 濮阳县| 沾化县| 沅陵县| 鄯善县| 东莞市| 巴青县| 左贡县| 金门县| 疏附县| 峨眉山市| 石台县| 谢通门县| 梅州市| 信宜市| 博客| 内丘县| 九寨沟县| 高安市| 涞源县| 张家港市| 阿合奇县| 乃东县| 若羌县| 贵港市| 体育| 棋牌|