為正確理解static在應用於內部類時的含義,必須記住內部類的對象默認持有創建它的那個封裝類的一個對象的句柄。然而,假如我們說一個內部類是static的,這種說法卻是不成立的。static內部類意味著:
(1) 為創建一個static內部類的對象,我們不需要一個外部類對象。
(2) 不能從static內部類的一個對象中訪問一個外部類對象。
但在存在一些限制:由於static成員只能位於一個類的外部級別,所以內部類不可擁有static數據或static內部類。
倘若為了創建內部類的對象而不需要創建外部類的一個對象,那麼可將所有東西都設為static。為了能正常工作,同時也必須將內部類設為static。如下所示:
//: Parcel10.java
// Static inner classes
package c07.parcel10;
abstract class Contents {
abstract public int value();
}
interface Destination {
String readLabel();
}
public class Parcel10 {
private static class PContents
extends Contents {
private int i = 11;
public int value() { return i; }
}
protected static class PDestination
implements Destination {
private String label;
private PDestination(String whereTo) {
label = whereTo;
}
public String readLabel() { return label; }
}
public static Destination dest(String s) {
return new PDestination(s);
}
public static Contents cont() {
return new PContents();
}
public static void main(String[] args) {
Contents c = cont();
Destination d = dest("Tanzania");
}
} ///:~
在main()中,我們不需要Parcel10的對象;相反,我們用常規的語法來選擇一個static成員,以便調用將句柄返回Contents和Destination的方法。
通常,我們不在一個接口裡設置任何代碼,但static內部類可以成為接口的一部分。由於類是“靜態”的,所以它不會違反接口的規則——static內部類只位於接口的命名空間內部:
//: IInterface.java
// Static inner classes inside interfaces
interface IInterface {
static class Inner {
int i, j, k;
public Inner() {}
void f() {}
}
} ///:~
在本書早些時候,我建議大家在每個類裡都設置一個main(),將其作為那個類的測試床使用。這樣做的一個缺點就是額外代碼的數量太多。若不願如此,可考慮用一個static內部類容納自己的測試代碼。如下所示:
//: TestBed.java
// Putting test code in a static inner class
class TestBed {
TestBed() {}
void f() { System.out.println("f()"); }
public static class Tester {
public static void main(String[] args) {
TestBed t = new TestBed();
t.f();
}
}
} ///:~
這樣便生成一個獨立的、名為TestBed$Tester的類(為運行程序,請使用“java TestBed$Tester”命令)。可將這個類用於測試,但不需在自己的最終發行版本中包含它。