1. 程式人生 > >介紹巢狀類和內部類

介紹巢狀類和內部類

在另一個類中定義的類就是巢狀類(nested classes)。巢狀類的範圍由裝入它的類的範圍限制。這樣,如果類B被定義在類A之內,那麼B為A所知,然而不被A的外面所知。巢狀類可以訪問巢狀它的類的成員,包括private 成員。但是,包圍類不能訪問巢狀類的成員。

巢狀類一般有2種類型:前面加static識別符號的和不加static 識別符號的。一個static的巢狀類有static修飾符。因為它是static,所以只能通過物件來訪問它包圍類的成員。也就是說,它不能直接引用它包圍類的成員。因為有這個限制,所以static巢狀類很少使用。

巢狀類最重要的型別是內部類(inner class)。內部類是非static的巢狀類。它可以訪問它的外部類的所有變數和方法,它可以直接引用它們,就像外部類中的其他非static成員的功能一樣。這樣,一個內部類完全在它的包圍類的範圍之內。

下面的程式示例瞭如何定義和使用一個內部類。名為Outer 的類有一個名為outer_x 的示例變數,一個名為test()的例項方法,並且定義了一個名為Inner 的內部類。

// Demonstrate an inner class.
class Outer {
int outer_x = 100;

void test() {
Inner inner = new Inner();
inner.display();

}

// this is an inner class class Inner { void display() {System.out.println("display: outer_x = " + outer_x); }}}

class InnerClassDemo {

public static void main(String args[]) {
Outer outer = new Outer();
outer.test();

}
}

該程式的輸出如下所示:

display: outer_x = 100

在本程式中,內部類Inner 定義在Outer 類的範圍之內。因此,在Inner 類之內的任何程式碼可以直接訪問變數outer_x 。例項方法display() 定義在Inner 的內部,該方法以標準的輸出流顯示 outer_x 。InnerClassDemo 的main( ) 方法建立類Outer 的一個例項並呼叫它的test( )方法。建立類Inner 和display() 方法的一個例項的方法被呼叫。

認識到Inner 類只有在類Outer 的範圍內才是可知的是很重要的。如果在類Outer 之外的任何程式碼試圖例項化Inner 類,Java 編譯器會產生一條錯誤訊息。總體來說,一個巢狀類和其他任何另外的程式設計元素沒有什麼不同:它僅僅在它的包圍範圍內是可知的。

我們解釋過,一個內部類可以訪問它的包圍類的成員,但是反過來就不成立了。內部類的成員只有在內部類的範圍之內是可知的,而且不能被外部類使用。例如:

// This program will not compile.
class Outer {
int outer_x = 100;

void test() {
Inner inner = new Inner();
inner.display();

}

// this is an inner class
class Inner {
int y = 10; // y is local to Inner
void display() {

System.out.println("display: outer_x = " + outer_x);
}
}

void showy() { System.out.println(y); // error,y not known here!}}

class InnerClassDemo {

public static void main(String args[]) {
Outer outer = new Outer();
outer.test();

}
}

這裡,y是作為Inner 的一個例項變數來宣告的。這樣對於該類的外部它就是不可知的,因此不能被showy() 使用。

儘管我們強調巢狀類在它的外部類的範圍之內宣告,但在幾個程式塊的範圍之內定義內部類是可能的。例如,在由方法定義的塊中,或甚至在for 迴圈體內部,你也可以定義巢狀類,如下面的程式所示:

// Define an inner class within a for loop.
class Outer {
int outer_x = 100;

void test() { for(int i=0; i<10; i++) { class Inner { void display() {System.out.println("display: outer_x = " + outer_x);

}
}
Inner inner = new Inner();
inner.display();

}
}
}

class InnerClassDemo {

public static void main(String args[]) {
Outer outer = new Outer();
outer.test();

}
}

該程式的這個版本的輸出如下所示。

display: outer_x = 100
display: outer_x = 100
display: outer_x = 100

display: outer_x = 100
display: outer_x = 100
display: outer_x = 100
display: outer_x = 100
display: outer_x = 100
display: outer_x = 100
display: outer_x = 100

儘管巢狀類在日常的大多數程式設計中不使用,但當處理applet (小應用程式)時是特別有幫助的。在第20章中我們將繼續巢狀類的話題。在那裡你將看到對於某些型別的事件內部類如何被用來簡化程式碼。你也將瞭解匿名內部類(anonymous inner classes),它是一個沒有名字的內部類。

最後一點:巢狀類在Java 的最初的1.0版本中是不允許的。直到Java 1.1 中才添加了巢狀類。