內部類
內部類(inner class)是定義在另一個類中的類,為什么要使用內部類呢?其主要原因有以下三點:
1.內部類方法可以訪問該類定義所在的作用域中的數據,包括私有數據。
2.內部類可以對同一個包中的其他類隱藏起來。
3.當想要定義一個回調函數且不想編寫大量代碼時,使用匿名內部類比較便捷。
1.使用內部類訪問對象狀態
只有內部類可以是私有類,而常規的類只能具有包的可見性,或公有的可見性。
內部類的對象有一個隱式引用(這個引用在內部類的定義中是不可見的),它引用了實例化該內部類對象的外圍類對象。通過這個指針,可以訪問外圍類對象的全部狀態。
所以,內部類既可以訪問自身的數據域,也可以訪問創建它的外圍類對象的數據域。
2.內部類的特殊語法規則
使用外圍類引用的正規語法:
OuterClass.this
可以采用下列語法格式更加明確地編寫內部對象的構造器:
OuterObject.new InnerClass(construction parameters)
在外圍類的作用域之外,可以這樣引用內部類:
OuterClass.InnerClass
3.內部類是否實用、必要和安全
內部類是一種編譯器現象,與虛擬機無關。編譯器將會把內部類翻譯成用美元符號$分隔外部類名與內部類名的常規類文件,而虛擬機對此一無所知。
編譯器為了引用外部類,生成了一個附加的實例域this$0。
編譯器在外圍類添加靜態方法access$100。
這樣內部類與常規類比起來就具有了額外的訪問特權,而虛擬機對此並不了解。
如果內部類訪問了私有數據域,那么就有可能通過附加在外圍類所在包中的其他類訪問它們,但做這些事情需要高超的技巧和極大的決心。
4.局部內部類
可以在一個方法中定義局部類。
局部類不能用public或private訪問說明符進行聲明,它的作用域被限定在聲明該局部類的塊中。局部類的一個優勢即對外部世界可以完全地隱藏起來。
局部類還有一個優勢,它們不僅能夠訪問包含它們的外圍類的域,而且還可以訪問局部變量,不過這些局部變量必須被聲明為final,對它進行初始化后不能夠再修改。
編譯器必須檢測對局部變量的訪問,為每一個變量建立相應的數據域,並將局部變量拷貝到構造器中,以便將這些數據域初始化為局部變量的副本。
5.匿名內部類
假如只創建這個類的一個對象,就不必為它命名了,這種類被稱為匿名內部類。
通常的語法格式為:
new SuperType(construction parameters)
{
inner class methods and data
}
SuperType可以是類也可以是接口。
由於構造器的名字必須和類名相同,而匿名類沒有類名,所以匿名類不能有構造器。
6.靜態內部類
有時候使用內部類只是為了把一個類隱藏在另外一個類的內部,並不需要內部類引用外圍類對象。為此,可以將內部類聲明為static,以便取消產生的引用。
即public static class ClassName
只有內部類可以聲明為static。
靜態內部類的對象除了沒有對生成它的外圍類對象的引用特權外,與其他內部類完全一樣。
注意,聲明在接口中的內部類自動成為public和static。