嵌套類
Java編程語言允許你在另一個類中定義類,這樣的類稱為嵌套類,如下所示:
class OuterClass { ... class NestedClass { ... } }
術語:嵌套類分為兩類:靜態和非靜態,聲明為static的嵌套類稱為靜態嵌套類,非靜態嵌套類稱為內部類。
class OuterClass { ... static class StaticNestedClass { ... } class InnerClass { ... } }
嵌套類是其封閉類的成員,非靜態嵌套類(內部類)可以訪問封閉類的其他成員,即使它們被聲明為private,靜態嵌套類無權訪問封閉類的其他成員。作為OuterClass的成員,可以將嵌套類聲明為private、public、protected或包私有(回想一下,外部類只能聲明為public或包私有)。
為什么使用嵌套類?使用嵌套類的令人信服的理由包括:
這是一種邏輯分組僅在一個地方使用的類的方法:如果一個類只對另一個類有用,那么將它嵌入該類并將兩者保持在一起是合乎邏輯的,嵌套這樣的“幫助類”使得它們的包更加簡化。
它增加了封裝:考慮兩個頂級類A和B,其中B需要訪問A的成員,否則這些成員將被聲明為private,通過將類B隱藏在類A中,可以將A的成員聲明為私有,并且B可以訪問它們,另外,B本身也可以不被外界發現。
它可以使代碼更具可讀性和可維護性:在頂級類中嵌套小類會使代碼更接近于使用它的位置。
靜態嵌套類與類方法和變量一樣,靜態嵌套類與其外部類相關聯,和靜態類方法一樣,靜態嵌套類不能直接引用其封閉類中定義的實例變量或方法:它只能通過對象引用來使用它們。
注意:靜態嵌套類與其外部類(和其他類)的實例成員交互,就像任何其他頂級類一樣,實際上,靜態嵌套類在行為上是一個頂級類,它已嵌套在另一個頂級類中以方便打包。
使用封閉的類名訪問靜態嵌套類:
OuterClass.StaticNestedClass
例如,要為靜態嵌套類創建對象,請使用以下語法:
OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();內部類
與實例方法和變量一樣,內部類與其封閉類的實例相關聯,并且可以直接訪問該對象的方法和字段,此外,由于內部類與實例相關聯,因此本身無法定義任何靜態成員。
作為內部類的實例的對象存在于外部類的實例中,考慮以下類:
class OuterClass { ... class InnerClass { ... } }
InnerClass的實例只能存在于OuterClass的實例中,并且可以直接訪問其封閉實例的方法和字段。
要實例化內部類,必須首先實例化外部類,然后,使用以下語法在外部對象中創建內部對象:
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
有兩種特殊的內部類:局部類和匿名類。
遮蔽如果特定范圍(例如內部類或方法定義)中的類型聲明(例如成員變量或參數名稱)與封閉范圍中的另一個聲明具有相同的名稱,然后聲明會影響封閉范圍的聲明,你不能僅通過其名稱引用遮蔽的聲明,以下示例ShadowTest演示了這一點:
public class ShadowTest { public int x = 0; class FirstLevel { public int x = 1; void methodInFirstLevel(int x) { System.out.println("x = " + x); System.out.println("this.x = " + this.x); System.out.println("ShadowTest.this.x = " + ShadowTest.this.x); } } public static void main(String... args) { ShadowTest st = new ShadowTest(); ShadowTest.FirstLevel fl = st.new FirstLevel(); fl.methodInFirstLevel(23); } }
以下是此示例的輸出:
x = 23 this.x = 1 ShadowTest.this.x = 0
此示例定義了三個名為x的變量:ShadowTest類的成員變量、內部類FirstLevel的成員變量、以及方法methodInFirstLevel中的參數。變量x定義為方法methodInFirstLevel的參數遮蔽內部類FirstLevel的變量,因此,當你在方法methodInFirstLevel中使用變量x時,它引用方法參數,要引用內部類FirstLevel的成員變量,請使用關鍵字this來表示封閉范圍:
System.out.println("this.x = " + this.x);
引用成員變量,這些成員變量根據所屬的類名包含更大的作用域,例如,以下語句從方法methodInFirstLevel訪問類ShadowTest的成員變量:
System.out.println("ShadowTest.this.x = " + ShadowTest.this.x);序列化
強烈建議不要對內部類(包括局部類和匿名類)進行序列化,當Java編譯器編譯某些構造(如內部類)時,它會創建合成構造,這些是類、方法、字段和其他在源代碼中沒有相應構造的構造。合成構造使Java編譯器能夠在不更改JVM的情況下實現new的Java語言功能,但是,合成構造可以在不同的Java編譯器實現之間變化,這意味著.class文件也可以在不同的實現之間變化。因此,如果序列化內部類,然后使用其他JRE實現反序列化,則可能存在兼容性問題,有關在編譯內部類時生成的合成構造的更多信息,請參閱獲取方法參數名稱一節中的隱式和合成參數部分。
內部類示例要看內部類的使用,首先要考慮一個數組,在下面的示例中,你將創建一個數組,用整數值填充它,然后僅按升序輸出數組的偶數索引值。
下面的DataStructure.java示例包括:
DataStructure外部類,它包含一個構造函數,用于創建DataStructure的實例,該實例包含一個數組,該數組填充了連續的整數值(0、1、2、3等等),以及一個方法,該方法打印具有偶數索引值的數組元素。
EvenIterator內部類,它實現了繼承了Iterator< Integer>接口的DataStructureIterator接口,迭代器用于逐步執行數據結構,通常有方法來測試最后一個元素,檢索當前元素,然后移動到下一個元素。
實例化DataStructure對象(ds)的main方法,然后調用printEven方法來打印具有偶數索引值的數組arrayOfInts的元素。
public class DataStructure { // Create an array private final static int SIZE = 15; private int[] arrayOfInts = new int[SIZE]; public DataStructure() { // fill the array with ascending integer values for (int i = 0; i < SIZE; i++) { arrayOfInts[i] = i; } } public void printEven() { // Print out values of even indices of the array DataStructureIterator iterator = this.new EvenIterator(); while (iterator.hasNext()) { System.out.print(iterator.next() + " "); } System.out.println(); } interface DataStructureIterator extends java.util.Iterator{ } // Inner class implements the DataStructureIterator interface, // which extends the Iterator interface private class EvenIterator implements DataStructureIterator { // Start stepping through the array from the beginning private int nextIndex = 0; public boolean hasNext() { // Check if the current element is the last in the array return (nextIndex <= SIZE - 1); } public Integer next() { // Record a value of an even index of the array Integer retValue = Integer.valueOf(arrayOfInts[nextIndex]); // Get the next even element nextIndex += 2; return retValue; } } public static void main(String s[]) { // Fill the array with integer values and print out only // values of even indices DataStructure ds = new DataStructure(); ds.printEven(); } }
輸出是:
0 2 4 6 8 10 12 14
請注意,EvenIterator類直接引用DataStructure對象的arrayOfInts實例變量。
你可以使用內部類來實現輔助類,例如本示例中所示的類,要處理用戶界面事件,你必須知道如何使用內部類,因為事件處理機制會廣泛使用它們。
局部和匿名類還有兩種類型的內部類,你可以在方法體內聲明內部類,這些類稱為局部類,你還可以在方法體內聲明內部類,而無需命名該類,這些類稱為匿名類。
修飾符你可以對用于外部類的其他成員的內部類使用相同的修飾符,例如,你可以使用訪問修飾符private、public和protected來限制對內部類的訪問,就像你使用它們來限制對其他類成員的訪問一樣。
上一篇:類的更多方面 下一篇:局部類文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/72337.html
使用包成員 組成包的類型稱為包成員。 要從其包外部使用公共包成員,你必須執行以下操作之一: 通過其完全限定名稱引用該成員 導入包成員 導入成員的整個包 每種情況都適用于不同的情況,如以下各節所述。 通過其完全限定名稱引用包成員 到目前為止,本教程中的大多數示例都通過簡單名稱引用類型,例如Rectangle和StackOfInts,如果你編寫的代碼與該成員位于同一個包中,或者已導入該成員,則可以...
繼承 在前面的課程中,你已經多次看到了繼承,在Java語言中,類可以從其他類派生,從而從這些類繼承字段和方法。 定義:從另一個類派生的類稱為子類(也是派生類,擴展類或子類),派生子類的類稱為超類(也是基類或父類)。 除了Object沒有超類,每個類都有一個且只有一個直接超類(單繼承),在沒有任何其他顯式超類的情況下,每個類都隱式地是Object的子類。 類可以從派生自類的類派生的類派生,依此類推,...
摘要:所以看出和兩個的對應指針數一樣,一個為一個為這就引出了變量的知識點,如手工畫的圖二為啥強制子類父類變量名不同阿里巴巴手冊是這樣寫的強制避免在子父類的成員變量之間或者不同代碼塊的局部變量之間采用完全相同的命名方式,那會導致代碼可讀性降低。 摘要: 原創出處 https://www.bysocket.com 「公眾號:泥瓦匠BYSocket 」歡迎關注和轉載,保留摘要,謝謝! 目錄 父子...
Java? 教程 Java教程是為JDK 8編寫的,本頁面中描述的示例和實踐沒有利用在后續版本中引入的改進。 Java教程是希望使用Java編程語言創建應用程序的程序員的實用指南,其中包括數百個完整的工作示例和數十個課程,相關課程組被組織成教程。 覆蓋基礎知識的路徑 這些教程以書籍的形式提供,如Java教程,第六版,前往Amazon.com購買。 入門 介紹Java技術和安裝Java開發軟件并使用...
閱讀 948·2021-11-22 12:09
閱讀 3715·2021-09-27 13:36
閱讀 1406·2021-08-20 09:37
閱讀 4029·2019-12-27 12:22
閱讀 2366·2019-08-30 15:55
閱讀 2371·2019-08-30 13:16
閱讀 2832·2019-08-26 17:06
閱讀 3443·2019-08-23 18:32