<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    keep moving!

    We must not cease from exploration. And the end of all our exploring will be to arrive where we began and to know the place for the first time.
    隨筆 - 37, 文章 - 2, 評論 - 3, 引用 - 0
    數(shù)據(jù)加載中……

    Java內(nèi)部類1

    提起Java內(nèi)部類(Inner Class)可能很多人不太熟悉,實(shí)際上類似的概念在C++里也有,那就是嵌套類(Nested Class),關(guān)于這兩者的區(qū)別與聯(lián)系,在下文中會(huì)有對比。內(nèi)部類從表面上看,就是在類中又定義了一個(gè)類(下文會(huì)看到,內(nèi)部類可以在很多地方定義),而實(shí)際上并沒有那么簡單,乍看上去內(nèi)部類似乎有些多余,它的用處對于初學(xué)者來說可能并不是那么顯著,但是隨著對它的深入了解,你會(huì)發(fā)現(xiàn)Java的設(shè)計(jì)者在內(nèi)部類身上的確是用心良苦。學(xué)會(huì)使用內(nèi)部類,是掌握J(rèn)ava高級(jí)編程的一部分,它可以讓你更優(yōu)雅地設(shè)計(jì)你的程序結(jié)構(gòu)。下面從以下幾個(gè)方面來介紹:

      第一次見面

    public interface Contents {
     int value();
    }

    public interface Destination {
     String readLabel();
    }

    public class Goods {
     private class Content implements Contents {
      private int i = 11;
      public int value() { 
       return i; 
      }
     }

     protected class GDestination implements Destination {
      private String label;
      private GDestination(String whereTo) {
       label = whereTo;
      }
      public String readLabel() { 
       return label; 
      }
     }

     public Destination dest(String s) {
      return new GDestination(s);
     }
     public Contents cont() {
      return new Content();
     }
    }

    class TestGoods {
     public static void main(String[] args) {
      Goods p = new Goods();
      Contents c = p.cont();
      Destination d = p.dest("Beijing");
     }
    }  

      在這個(gè)例子里類Content和GDestination被定義在了類Goods內(nèi)部,并且分別有著protected和private修飾符來控制訪問級(jí)別。Content代表著Goods的內(nèi)容,而GDestination代表著Goods的目的地。它們分別實(shí)現(xiàn)了兩個(gè)接口Content和Destination。在后面的main方法里,直接用 Contents c和Destination d進(jìn)行操作,你甚至連這兩個(gè)內(nèi)部類的名字都沒有看見!這樣,內(nèi)部類的第一個(gè)好處就體現(xiàn)出來了??隱藏你不想讓別人知道的操作,也即封裝性。 

      同時(shí),我們也發(fā)現(xiàn)了在外部類作用范圍之外得到內(nèi)部類對象的第一個(gè)方法,那就是利用其外部類的方法創(chuàng)建并返回。上例中的cont()和dest()方法就是這么做的。那么還有沒有別的方法呢?當(dāng)然有,其語法格式如下:

    outerObject=new outerClass(Constructor Parameters);

    outerClass.innerClass innerObject=outerObject.new InnerClass(Constructor Parameters); 

      注意在創(chuàng)建非靜態(tài)內(nèi)部類對象時(shí),一定要先創(chuàng)建起相應(yīng)的外部類對象。至于原因,也就引出了我們下一個(gè)話題??非靜態(tài)內(nèi)部類對象有著指向其外部類對象的引用,對剛才的例子稍作修改:

    public class Goods {

     private valueRate=2;

     private class Content implements Contents {
      private int i = 11*valueRate;
      public int value() { 
       return i; 
      }
     }

     protected class GDestination implements Destination {
      private String label;
      private GDestination(String whereTo) {
       label = whereTo;
      }
      public String readLabel() { 
       return label; 
      }
     }

     public Destination dest(String s) {
      return new GDestination(s);
     }
     public Contents cont() {
      return new Content();
     }


      修改的部分用藍(lán)色顯示了。在這里我們給Goods類增加了一個(gè)private成員變量valueRate,意義是貨物的價(jià)值系數(shù),在內(nèi)部類Content的方法value()計(jì)算價(jià)值時(shí)把它乘上。我們發(fā)現(xiàn),value()可以訪問valueRate,這也是內(nèi)部類的第二個(gè)好處??一個(gè)內(nèi)部類對象可以訪問創(chuàng)建它的外部類對象的內(nèi)容,甚至包括私有變量!這是一個(gè)非常有用的特性,為我們在設(shè)計(jì)時(shí)提供了更多的思路和捷徑。要想實(shí)現(xiàn)這個(gè)功能,內(nèi)部類對象就必須有指向外部類對象的引用。Java編譯器在創(chuàng)建內(nèi)部類對象時(shí),隱式的把其外部類對象的引用也傳了進(jìn)去并一直保存著。這樣就使得內(nèi)部類對象始終可以訪問其外部類對象,同時(shí)這也是為什么在外部類作用范圍之外向要?jiǎng)?chuàng)建內(nèi)部類對象必須先創(chuàng)建其外部類對象的原因。

      有人會(huì)問,如果內(nèi)部類里的一個(gè)成員變量與外部類的一個(gè)成員變量同名,也即外部類的同名成員變量被屏蔽了,怎么辦?沒事,Java里用如下格式表達(dá)外部類的引用:

    outerClass.this  

      有了它,我們就不怕這種屏蔽的情況了。

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

      和普通的類一樣,內(nèi)部類也可以有靜態(tài)的。不過和非靜態(tài)內(nèi)部類相比,區(qū)別就在于靜態(tài)內(nèi)部類沒有了指向外部的引用。這實(shí)際上和C++中的嵌套類很相像了,Java內(nèi)部類與C++嵌套類最大的不同就在于是否有指向外部的引用這一點(diǎn)上,當(dāng)然從設(shè)計(jì)的角度以及以它一些細(xì)節(jié)來講還有區(qū)別。

      除此之外,在任何非靜態(tài)內(nèi)部類中,都不能有靜態(tài)數(shù)據(jù),靜態(tài)方法或者又一個(gè)靜態(tài)內(nèi)部類(內(nèi)部類的嵌套可以不止一層)。不過靜態(tài)內(nèi)部類中卻可以擁有這一切。這也算是兩者的第二個(gè)區(qū)別吧。

      局部內(nèi)部類 

      是的,Java內(nèi)部類也可以是局部的,它可以定義在一個(gè)方法甚至一個(gè)代碼塊之內(nèi)。

    public class Goods1 {
     public Destination dest(String s) {
      class GDestination implements Destination {
       private String label;
       private GDestination(String whereTo) {
        label = whereTo;
       }
       public String readLabel() { return label; }
      }
      return new GDestination(s);
     }

     public static void main(String[] args) {
      Goods1 g= new Goods1();
      Destination d = g.dest("Beijing");
     }


      上面就是這樣一個(gè)例子。在方法dest中我們定義了一個(gè)內(nèi)部類,最后由這個(gè)方法返回這個(gè)內(nèi)部類的對象。如果我們在用一個(gè)內(nèi)部類的時(shí)候僅需要?jiǎng)?chuàng)建它的一個(gè)對象并創(chuàng)給外部,就可以這樣做。當(dāng)然,定義在方法中的內(nèi)部類可以使設(shè)計(jì)多樣化,用途絕不僅僅在這一點(diǎn)。

      下面有一個(gè)更怪的例子:

    public class Goods2{
     private void internalTracking(boolean b) {
      if(b) {
       class TrackingSlip {
        private String id;
        TrackingSlip(String s) {
         id = s;
        }
        String getSlip() { return id; }
       }
       TrackingSlip ts = new TrackingSlip("slip");
       String s = ts.getSlip();
      } 
     }

     public void track() { internalTracking(true); }

     public static void main(String[] args) {
      Goods2 g= new Goods2();
      g.track();
     }


      你不能在if之外創(chuàng)建這個(gè)內(nèi)部類的對象,因?yàn)檫@已經(jīng)超出了它的作用域。不過在編譯的時(shí)候,內(nèi)部類TrackingSlip和其他類一樣同時(shí)被編譯,只不過它由它自己的作用域,超出了這個(gè)范圍就無效,除此之外它和其他內(nèi)部類并沒有區(qū)別。

      匿名內(nèi)部類 

      java的匿名內(nèi)部類的語法規(guī)則看上去有些古怪,不過如同匿名數(shù)組一樣,當(dāng)你只需要?jiǎng)?chuàng)建一個(gè)類的對象而且用不上它的名字時(shí),使用內(nèi)部類可以使代碼看上去簡潔清楚。它的語法規(guī)則是這樣的:

    new interfacename(){......}; 或 new superclassname(){......};  

      下面接著前面繼續(xù)舉例子:

    public class Goods3 {
     public Contents cont(){
      return new Contents(){
       private int i = 11;
       public int value() { 
        return i; 
       }
      };
     }
    }  

      這里方法cont()使用匿名內(nèi)部類直接返回了一個(gè)實(shí)現(xiàn)了接口Contents的類的對象,看上去的確十分簡潔。

      在java的事件處理的匿名適配器中,匿名內(nèi)部類被大量的使用。例如在想關(guān)閉窗口時(shí)加上這樣一句代碼:

    frame.addWindowListener(new WindowAdapter(){
     public void windowClosing(WindowEvent e){
      System.exit(0); 
     }
    }); 

      有一點(diǎn)需要注意的是,匿名內(nèi)部類由于沒有名字,所以它沒有構(gòu)造函數(shù)(但是如果這個(gè)匿名內(nèi)部類繼承了一個(gè)只含有帶參數(shù)構(gòu)造函數(shù)的父類,創(chuàng)建它的時(shí)候必須帶上這些參數(shù),并在實(shí)現(xiàn)的過程中使用super關(guān)鍵字調(diào)用相應(yīng)的內(nèi)容)。如果你想要初始化它的成員變量,有下面幾種方法:

      如果是在一個(gè)方法的匿名內(nèi)部類,可以利用這個(gè)方法傳進(jìn)你想要的參數(shù),不過記住,這些參數(shù)必須被聲明為final。 

      將匿名內(nèi)部類改造成有名字的局部內(nèi)部類,這樣它就可以擁有構(gòu)造函數(shù)了。 

      在這個(gè)匿名內(nèi)部類中使用初始化代碼塊。 

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

      java內(nèi)部類有什么好處?為什么需要內(nèi)部類?

      首先舉一個(gè)簡單的例子,如果你想實(shí)現(xiàn)一個(gè)接口,但是這個(gè)接口中的一個(gè)方法和你構(gòu)想的這個(gè)類中的一個(gè)方法的名稱,參數(shù)相同,你應(yīng)該怎么辦?這時(shí)候,你可以建一個(gè)內(nèi)部類實(shí)現(xiàn)這個(gè)接口。由于內(nèi)部類對外部類的所有內(nèi)容都是可訪問的,所以這樣做可以完成所有你直接實(shí)現(xiàn)這個(gè)接口的功能。

      不過你可能要質(zhì)疑,更改一下方法的不就行了嗎?

      的確,以此作為設(shè)計(jì)內(nèi)部類的理由,實(shí)在沒有說服力。

      真正的原因是這樣的,java中的內(nèi)部類和接口加在一起,可以的解決常被C++程序員抱怨java中存在的一個(gè)問題??沒有多繼承。實(shí)際上,C++的多繼承設(shè)計(jì)起來很復(fù)雜,而java通過內(nèi)部類加上接口,可以很好的實(shí)現(xiàn)多繼承的效果。

    posted on 2008-09-07 11:41 大石頭 閱讀(184) 評論(0)  編輯  收藏 所屬分類: 基礎(chǔ)

    主站蜘蛛池模板: 夫妻免费无码V看片| 中文字幕无码日韩专区免费| 青娱分类视频精品免费2| 香港特级三A毛片免费观看| 黄a大片av永久免费| 亚洲gv猛男gv无码男同短文| 免费中文字幕视频| 亚洲精品国产精品乱码不卞| eeuss影院www天堂免费| 毛片a级毛片免费观看品善网| 亚洲午夜电影在线观看高清 | 成人毛片视频免费网站观看| 亚洲kkk4444在线观看| 免费看少妇作爱视频| 免费人成大片在线观看播放| 亚洲精品亚洲人成在线观看下载| 久久国产精品免费一区| 久久精品国产亚洲| 国产乱子精品免费视观看片| 亚洲AV无码乱码麻豆精品国产| 欧美最猛性xxxxx免费| 在线观看亚洲免费| 最近最新MV在线观看免费高清| 亚洲乱码国产乱码精华| 84pao强力永久免费高清| 亚洲制服在线观看| 日韩一区二区三区免费体验| 日韩在线视频免费| 久久亚洲国产视频| 久久久精品午夜免费不卡| 激情内射亚洲一区二区三区| 免费做爰猛烈吃奶摸视频在线观看| 粉色视频成年免费人15次| 色久悠悠婷婷综合在线亚洲| 狠狠热精品免费观看| 亚洲国产另类久久久精品| 青苹果乐园免费高清在线| 又黄又大的激情视频在线观看免费视频社区在线| 亚洲老妈激情一区二区三区| jizz免费在线影视观看网站| 亚洲视频在线观看地址|