1. 程式人生 > >在方法和作用域內的內部類

在方法和作用域內的內部類

目前為止,你所看到的只是內部類典型的用途。通常,如果你要讀寫的程式碼包含了內部類,
那麼它們都是“平凡的”內部類,簡單並且容易理解。然而,內部類的設計卻是相當完備
的。如果你選擇使用內部類,它還有許多難以理解的使用方式。例如,可以在一個方法裡
面或者在任意的作用域內定義內部類。這麼做有兩個理由:


1.如前所示,你實現了某型別的介面,於是可以建立並返回對其的引用。
2.你要解決一個複雜的問題,想建立一個類來輔助你的解決方案,但是又不希望
這個類是公共可用的。


在後面的例子中,先前的程式碼將被修改以用來實現:


1.一個定義在方法中的類
2.一個定義在作用域內的類,此作用域在方法的內部
3.一個實現了介面的匿名類
4. 一個匿名類,擴充套件了有非預設構造器的類
5. 一個匿名類,執行成員初始化
6. 一個匿名類,通過例項初始化實現構造(匿名類不可能有構造器)


雖然 Wrapping 只是一個普通的類,但同時也被其匯出類作為通用“介面”使用。


//: c08:Wrapping.java
publicclass Wrapping { 
privateint i;
public Wrapping(int x) { i = x; } 
publicint value() {return i; } 
}///:~


請注意 Wrapping 的構造器,它需要一個引數,這使得事情更有趣了。
 






第一個例子展示了在方法的作用域內(而不是在其它類的作用域內)建立一個完整的類。
這被稱作區域性內部類(local inner class):


//: c08:Parcel4.java
// Nesting a class within a method.


publicclass Parcel4 {
public Destination dest(String s) { 
class PDestinationimplements Destination {
private String label;
private PDestination(String whereTo) {
        label = whereTo; 
      }
public String readLabel() {return label; } 
    }
returnnew PDestination(s); 
  }
publicstatic void main(String[] args) { 
    Parcel4 p = new Parcel4(); 
    Destination d = p.dest("Tanzania");
  }
}///:~


與其說 PDestination 類是 Parcel4 的一部分,不如說是 dest()方法的一部分。(要注意
到,你可以在同一個子目錄下的任意類中定義名為 PDestination 的內部類,這並不會有命
名衝突。)所以,在 dest()之外不能訪問 PDestination。注意出現在 return 語句中的向
上轉型——返回的是 Destination 的引用,它是 PDestination 的基類。當然,在 dest()
中定義了內部類 PDestination,並不意味著一旦 dest()方法執行完畢,PDestination 就
不可用了。


下一個例子展示瞭如何在任意的作用域內嵌入一個內部類:


//: c08:Parcel5.java
// Nesting a class within a scope.


publicclass Parcel5 {
privatevoid 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(); 
    }
// Can't use it here! Out of scope:
//! TrackingSlip ts = new TrackingSlip("x");
  }
publicvoid track() { internalTracking(true); } 
publicstatic void main(String[] args) { 
    Parcel5 p = new Parcel5(); 
    p.track();
  }
}///:~


TrackingSlip 類被嵌入在 if 語句的作用域內,這並不是說它的建立是有條件的,它其實與
別的類一樣都經過編譯了。然而,在定義 TrackingSlip 的作用域之外,它是不可用的。除

此之外,它與普通的類一樣。