使用內部和匿名類最佳化Java程式碼(轉)
使用內部和匿名類最佳化Java程式碼(轉)[@more@]Java 1.1透過對Java語言規範進行修改,顯著簡化了一些實用結構的實現。在那些修改中,最引人注目的就是內部類和匿名類。如運用得當,它們可使程式更易理解和維護。下面來看看這些特性具體是如何工作的,如何正確使用它們,以及如何避免一些常見的錯誤。
內部類
簡單地說,“內部類”是在另一個類的內部宣告的類。從Java 1.1開始,你可在一個類中宣告另一個類,這與宣告欄位和方法非常相似。包裝了內部類宣告的類就稱為“外部類”。
實際上,Java語言規範還允許你做更多的事情,包括:
在另一個類或者一個介面中宣告一個類。
在另一個介面或者一個類中宣告一個介面。
在一個方法中宣告一個類。
類和介面宣告可巢狀任意深度。
清單A是類和介面的一些空白宣告,它演示了這些可能性。
使用一個import語句,你可像使用其他任何標準類那樣省略package名稱。此外,在外部類中,可利用簡單名稱來引用所有內部類和介面(參見清單A中的new語句)。注意從Method1中引用Inner2仍需指定Interface1,因為Inner2在一個不同的級別上。
表A總結了清單A中宣告的每個內部類和介面的完全限定名稱。用了import語句之後,就可採用較短的形式。當然,在外部類中,你還可省略外部類的名稱。
名稱
類/介面
Inner1 mypackage.Inner1
Interface1 mypackage.Interface1
Inner2 mypackage.Interface1.Inner2
Interface2 mypackage.Interface1.Interface2
Inner3 Inner3對於Method1來說是local的,所以它不可在方法外部訪問
引用內部類
內部類最自然的一種應用就是宣告只在另一個類的內部使用的類,或者宣告與另一個類密切相關的類。如清單B所示,它是一個連結串列的簡單實現。由於Node類通常只在LinkedList的範圍內使用,所以最好將Node宣告為LinkedList的一個內部類。
適用於類成員的訪問控制修改符也適用於內部類;也就是說,內部類可以具有package、protected、private和public訪問許可權,它們的語義和正常的語義沒有什麼不同。由於Node要在LinkedList的外部使用,所以把它宣告為public。
然而,修飾符static具有不同的含義。應用於內部類時,它宣告的類具有與其他類相同的語義,也就是可進行例項化,並像一個標準類那樣使用。惟一的區別就是它擁有對外部類的所有靜態成員的完全訪問許可權。清單C展示了一個簡單的程式,它建立一個連結串列,並將它列印到標準輸出裝置。
非靜態內部類
如果內部類沒有指定static修飾符,就擁有對外部類的所有成員的完全訪問許可權,包括例項欄位和方法。為實現這一行為,非靜態內部類儲存著對外部類的例項的一個隱式引用。
所以,對一個非靜態內部類進行例項化需要採用不同語法的new語句:
.new
這種形式的new語句要求外部類的一個例項,使內部類能在那個例項的上下文中建立。注意清單A宣告瞭幾個非靜態內部類,並用標準的new語句在Method1中例項化它們。
之所以能那樣做,是因為Method1是外部類的一個例項方法,所以new語句會在外部類的一個例項的上下文中隱式地執行。只有在外部類的外部或者在其他物件的上下文中例項化一個非靜態內部類時,才需要使用修改過的語法。
但是,非靜態內部類具有一些限制。尤其是,它們不能宣告靜態初始化列表和靜態成員,除非是在常量欄位中。此外,方法內部宣告的內部類不能訪問方法的區域性變數和引數,除非它們被初始化成final。
匿名類
匿名類是不能有名稱的類,所以沒辦法引用它們。必須在建立時,作為new語句的一部分來宣告它們。
這就要採用另一種形式的new語句,如下所示:
new
這種形式的new語句宣告一個新的匿名類,它對一個給定的類進行擴充套件,或者實現一個給定的介面。它還建立那個類的一個新例項,並把它作為語句的結果而返回。要擴充套件的類和要實現的介面是new語句的運算元,後跟匿名類的主體。
如果匿名類對另一個類進行擴充套件,它的主體可以訪問類的成員、覆蓋它的方法等等,這和其他任何標準的類都是一樣的。如果匿名類實現了一個介面,它的主體必須實現介面的方法。
注意匿名類的宣告是在編譯時進行的,例項化在執行時進行。這意味著for迴圈中的一個new語句會建立相同匿名類的幾個例項,而不是建立幾個不同匿名類的一個例項。
從技術上說,匿名類可被視為非靜態的內部類,所以它們具有和方法內部宣告的非靜態內部類一樣的許可權和限制。
如果要執行的任務需要一個物件,但卻不值得建立全新的物件(原因可能是所需的類過於簡單,或者是由於它只在一個方法內部使用),匿名類就顯得非常有用。匿名類尤其適合在Swing應用程式中快速建立事件處理程式。
清單D就是一個非常簡單的Swing應用程式,它展示了與匿名類有關的幾個概念。這個例子建立了兩個匿名類。第一個對java.awt.event.WindowAdapter進行擴充套件,並在應用程式視窗關閉時呼叫應用程式的onClose方法。
即使onClose宣告為private,匿名類也能呼叫它,因為匿名類本質上是應用程式類的一個內部類。第二個匿名類實現了java.awt.ActionListener介面,它在一個按鈕被按下後關閉應用程式視窗。注意匿名類可以訪問本地變數frame。這是由於匿名類在與frame相同的方法內部宣告。然而,frame要被宣告為final,否則會生成編譯錯誤。
更最佳化的程式碼
內部和匿名類是Java 1.1為我們提供的兩個出色的工具。它們提供了更好的封裝,結果就是使程式碼更容易理解和維護,使相關的類都能存在於同一個原始碼檔案中(這要歸功於內部類),並能避免一個程式產生大量非常小的類(這要歸功於匿名類)。
內部類
簡單地說,“內部類”是在另一個類的內部宣告的類。從Java 1.1開始,你可在一個類中宣告另一個類,這與宣告欄位和方法非常相似。包裝了內部類宣告的類就稱為“外部類”。
實際上,Java語言規範還允許你做更多的事情,包括:
在另一個類或者一個介面中宣告一個類。
在另一個介面或者一個類中宣告一個介面。
在一個方法中宣告一個類。
類和介面宣告可巢狀任意深度。
清單A是類和介面的一些空白宣告,它演示了這些可能性。
使用一個import語句,你可像使用其他任何標準類那樣省略package名稱。此外,在外部類中,可利用簡單名稱來引用所有內部類和介面(參見清單A中的new語句)。注意從Method1中引用Inner2仍需指定Interface1,因為Inner2在一個不同的級別上。
表A總結了清單A中宣告的每個內部類和介面的完全限定名稱。用了import語句之後,就可採用較短的形式。當然,在外部類中,你還可省略外部類的名稱。
名稱
類/介面
Inner1 mypackage.Inner1
Interface1 mypackage.Interface1
Inner2 mypackage.Interface1.Inner2
Interface2 mypackage.Interface1.Interface2
Inner3 Inner3對於Method1來說是local的,所以它不可在方法外部訪問
引用內部類
內部類最自然的一種應用就是宣告只在另一個類的內部使用的類,或者宣告與另一個類密切相關的類。如清單B所示,它是一個連結串列的簡單實現。由於Node類通常只在LinkedList的範圍內使用,所以最好將Node宣告為LinkedList的一個內部類。
適用於類成員的訪問控制修改符也適用於內部類;也就是說,內部類可以具有package、protected、private和public訪問許可權,它們的語義和正常的語義沒有什麼不同。由於Node要在LinkedList的外部使用,所以把它宣告為public。
然而,修飾符static具有不同的含義。應用於內部類時,它宣告的類具有與其他類相同的語義,也就是可進行例項化,並像一個標準類那樣使用。惟一的區別就是它擁有對外部類的所有靜態成員的完全訪問許可權。清單C展示了一個簡單的程式,它建立一個連結串列,並將它列印到標準輸出裝置。
非靜態內部類
如果內部類沒有指定static修飾符,就擁有對外部類的所有成員的完全訪問許可權,包括例項欄位和方法。為實現這一行為,非靜態內部類儲存著對外部類的例項的一個隱式引用。
所以,對一個非靜態內部類進行例項化需要採用不同語法的new語句:
.new
這種形式的new語句要求外部類的一個例項,使內部類能在那個例項的上下文中建立。注意清單A宣告瞭幾個非靜態內部類,並用標準的new語句在Method1中例項化它們。
之所以能那樣做,是因為Method1是外部類的一個例項方法,所以new語句會在外部類的一個例項的上下文中隱式地執行。只有在外部類的外部或者在其他物件的上下文中例項化一個非靜態內部類時,才需要使用修改過的語法。
但是,非靜態內部類具有一些限制。尤其是,它們不能宣告靜態初始化列表和靜態成員,除非是在常量欄位中。此外,方法內部宣告的內部類不能訪問方法的區域性變數和引數,除非它們被初始化成final。
匿名類
匿名類是不能有名稱的類,所以沒辦法引用它們。必須在建立時,作為new語句的一部分來宣告它們。
這就要採用另一種形式的new語句,如下所示:
new
這種形式的new語句宣告一個新的匿名類,它對一個給定的類進行擴充套件,或者實現一個給定的介面。它還建立那個類的一個新例項,並把它作為語句的結果而返回。要擴充套件的類和要實現的介面是new語句的運算元,後跟匿名類的主體。
如果匿名類對另一個類進行擴充套件,它的主體可以訪問類的成員、覆蓋它的方法等等,這和其他任何標準的類都是一樣的。如果匿名類實現了一個介面,它的主體必須實現介面的方法。
注意匿名類的宣告是在編譯時進行的,例項化在執行時進行。這意味著for迴圈中的一個new語句會建立相同匿名類的幾個例項,而不是建立幾個不同匿名類的一個例項。
從技術上說,匿名類可被視為非靜態的內部類,所以它們具有和方法內部宣告的非靜態內部類一樣的許可權和限制。
如果要執行的任務需要一個物件,但卻不值得建立全新的物件(原因可能是所需的類過於簡單,或者是由於它只在一個方法內部使用),匿名類就顯得非常有用。匿名類尤其適合在Swing應用程式中快速建立事件處理程式。
清單D就是一個非常簡單的Swing應用程式,它展示了與匿名類有關的幾個概念。這個例子建立了兩個匿名類。第一個對java.awt.event.WindowAdapter進行擴充套件,並在應用程式視窗關閉時呼叫應用程式的onClose方法。
即使onClose宣告為private,匿名類也能呼叫它,因為匿名類本質上是應用程式類的一個內部類。第二個匿名類實現了java.awt.ActionListener介面,它在一個按鈕被按下後關閉應用程式視窗。注意匿名類可以訪問本地變數frame。這是由於匿名類在與frame相同的方法內部宣告。然而,frame要被宣告為final,否則會生成編譯錯誤。
更最佳化的程式碼
內部和匿名類是Java 1.1為我們提供的兩個出色的工具。它們提供了更好的封裝,結果就是使程式碼更容易理解和維護,使相關的類都能存在於同一個原始碼檔案中(這要歸功於內部類),並能避免一個程式產生大量非常小的類(這要歸功於匿名類)。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10617731/viewspace-960556/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Java內部類詳解--匿名內部類Java
- Java類與匿名內部類Java
- 匿名內部類的使用
- java內部類,區域性內部類,靜態內部類,匿名內部類Java
- 10-Java內部類——成員內部類、區域性內部類、匿名內部類Java
- 匿名內部類
- java培訓教程:什麼是匿名內部類?怎樣建立匿名內部類?Java
- java匿名內部類:“ 儂好,世界”Java
- Java中的匿名內部類及內部類的二三事Java
- 匿名內部類理解
- Java_介面回撥與匿名內部類Java
- Java之區域性匿名內部類物件Java物件
- 用匿名內部類實現 Java 同步回撥Java
- 關於java匿名內部類初始化法Java
- 內部類是什麼?匿名內部類又是什麼?
- java類內部程式碼執行順序Java
- 匿名內部類中關於new Runnable ( )
- Java 內部類使用詳解Java
- Java和ABAP裡的外部類和內部類Java
- java中的成員內部類,程式碼截圖Java
- Java內部類Java
- Java 內部類Java
- Java內部類詳解-- 成員內部類Java
- java內部類,為什麼需要內部類?Java
- 10、Java——內部類Java
- Java內部類詳解--區域性內部類Java
- scala_繼承、型別判斷、抽象類、匿名內部類繼承型別抽象
- 匿名內部類方式實現執行緒的建立執行緒
- Java基礎內部類4-內部類進階Java
- java中的內部類Java
- Java 內部類詳解Java
- Java內部類詳解Java
- Java-InnerClass內部類Java
- 淺談java內部類Java
- lambda表示式在oj中會比匿名內部類慢
- 《Java程式設計思想》筆記07——內部類Java程式設計筆記
- [短文速讀-3] 內部匿名類使用外部變數為什麼要加final變數
- Java 的抽象類, 介面以及內部類Java抽象
- Java 內部類與閉包Java