淺析Java語言中的內部類

azz發表於2007-08-24
淺析Java語言中的內部類[@more@]  提起Java內部類(Inner Class)可能很多人不太熟悉,實際上類似的概念在C++裡也有,那就是巢狀類(Nested Class),關於這兩者的區別與聯絡,在下文中會有對比。內部類從表面上看,就是在類中又定義了一個類(下文會看到,內部類可以在很多地方定義),而實際上並沒有那麼簡單,乍看上去內部類似乎有些多餘,它的用處對於初學者來說可能並不是那麼顯著,但是隨著對它的深入瞭解,你會發現Java的設計者在內部類身上的確是用心良苦。學會使用內部類,是掌握Java高階程式設計的一部分,它可以讓你更優雅地設計你的程式結構。下面從以下幾個方面來介紹:

  第一次見面

  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內部,並且分別有著protected和private修飾符來控制訪問級別。Content代表著Goods的內容,而GDestination代表著Goods的目的地。它們分別實現了兩個介面Content和Destination。在後面的main方法裡,直接用 Contents c和Destination d進行操作,你甚至連這兩個內部類的名字都沒有看見!這樣,內部類的第一個好處就體現出來了——隱藏你不想讓別人知道的操作,也即封裝性。

  同時,我們也發現了在外部類作用範圍之外得到內部類物件的第一個方法,那就是利用其外部類的方法建立並返回。上例中的cont()和dest()方法就是這麼做的。那麼還有沒有別的方法呢?當然有,其語法格式如下:

  outerObject=new outerClass(Constructor Parameters);

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

  注意在建立非靜態內部類物件時,一定要先建立起相應的外部類物件。至於原因,也就引出了我們下一個話題——非靜態內部類物件有著指向其外部類物件的引用,對剛才的例子稍作修改:

  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,意義是貨物的價值係數,在內部類Content的方法value()計算價值時把它乘上。我們發現,value()可以訪問valueRate,這也是內部類的第二個好處——一個內部類物件可以訪問建立它的外部類物件的內容,甚至包括私有變數!這是一個非常有用的特性,為我們在設計時提供了更多的思路和捷徑。要想實現這個功能,內部類物件就必須有指向外部類物件的引用。Java編譯器在建立內部類物件時,隱式的把其外部類物件的引用也傳了進去並一直儲存著。這樣就使得內部類物件始終可以訪問其外部類物件,同時這也是為什麼在外部類作用範圍之外向要建立內部類物件必須先建立其外部類物件的原因。

  有人會問,如果內部類裡的一個成員變數與外部類的一個成員變數同名,也即外部類的同名成員變數被遮蔽了,怎麼辦?沒事,Java裡用如下格式表達外部類的引用:

  outerClass.this

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

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10901326/viewspace-965634/,如需轉載,請註明出處,否則將追究法律責任。

相關文章