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

      第一次見面

    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");
     }
    }  

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

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

    outerObject=new outerClass(Constructor Parameters);

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

      注意在創(chuàng)建非靜態(tài)內(nèi)部類對象時,一定要先創(chuàng)建起相應的外部類對象。至于原因,也就引出了我們下一個話題??非靜態(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();
     }


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

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

    outerClass.this  

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

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

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

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

      局部內(nèi)部類 

      是的,Java內(nèi)部類也可以是局部的,它可以定義在一個方法甚至一個代碼塊之內(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");
     }


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

      下面有一個更怪的例子:

    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)建這個內(nèi)部類的對象,因為這已經(jīng)超出了它的作用域。不過在編譯的時候,內(nèi)部類TrackingSlip和其他類一樣同時被編譯,只不過它由它自己的作用域,超出了這個范圍就無效,除此之外它和其他內(nèi)部類并沒有區(qū)別。

      匿名內(nèi)部類 

      java的匿名內(nèi)部類的語法規(guī)則看上去有些古怪,不過如同匿名數(shù)組一樣,當你只需要創(chuàng)建一個類的對象而且用不上它的名字時,使用內(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)部類直接返回了一個實現(xiàn)了接口Contents的類的對象,看上去的確十分簡潔。

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

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

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

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

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

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

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

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

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

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

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

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

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

    主站蜘蛛池模板: 久久亚洲中文字幕精品一区四| 99无码人妻一区二区三区免费 | 亚洲Av无码乱码在线播放| 亚洲午夜无码久久久久小说| 歪歪漫画在线观看官网免费阅读 | 91短视频免费在线观看| 亚洲精品视频在线观看免费| 最近最好最新2019中文字幕免费 | 香蕉视频亚洲一级| 男人的天堂亚洲一区二区三区 | 亚洲ts人妖网站| 性盈盈影院免费视频观看在线一区| 亚洲 欧洲 视频 伦小说| 国内外成人免费视频| 亚洲av中文无码乱人伦在线观看| 四虎影视大全免费入口| 国产亚洲福利精品一区二区| 亚洲午夜激情视频| 中文字幕免费在线播放| 67pao强力打造67194在线午夜亚洲| 久久免费看黄a级毛片| 亚洲伊人久久大香线焦| 午夜视频免费成人| xxxxx做受大片视频免费| 亚洲AV成人无码久久精品老人 | 久久99毛片免费观看不卡| 亚洲视频在线一区二区三区| 成人免费无码大片a毛片| 特级毛片在线大全免费播放| 亚洲天天做日日做天天欢毛片| 亚欧免费一级毛片| 亚洲伊人久久大香线蕉AV| 亚洲国产av一区二区三区| 免费日本一区二区| 亚洲熟女乱色一区二区三区| 亚洲中文字幕无码爆乳AV| 无码国产精品一区二区免费虚拟VR| 国产精品亚洲一区二区三区久久 | 国产精成人品日日拍夜夜免费| 亚洲激情黄色小说| 亚洲成年看片在线观看|