四、靜態內部類與非靜態的區別
首先,靜態內部類實際上與普通類(即類名必須與文件名一樣的頂級類)一樣,只是靜態內部類在某一類的內部定義了而已,既然是類,要想使用就必須實例化。概念上與靜態變量、靜態方法是不一樣的,不要被“靜態”兩個字迷惑了(不要以爲凡是靜態的東西就不需要實例化就可以直接使用,靜態內部類是有區別),而且只有靜態內部類,而沒有靜態類(頂級類)的概念。例如,下面定義類是錯誤的:
public static class TestClass { // 此寫法錯誤,不存在靜態類,編譯不通過
public void test() {
}
}
如果你不需要內部類對象與其外部類對象之間有聯繫,那你可以將內部類聲明爲static。這通常稱爲嵌套類(nested class)。Static Nested Class是被聲明爲靜態(static)的內部類,它可以不依賴於外部類實例被實例化。而通常的內部類需要在外部類實例化後才能實例化。想要理解static應用於內部類時的含義,你就必須記住,普通的內部類對象隱含地保存了一個引用,指向創建它的外部類對象。然而,當內部類是static的時,就不是這樣了。嵌套類意味着:
1. 嵌套類的對象,並不需要其外部類的對象。
2. 不能從嵌套類的對象中訪問非靜態的外部類對象。
如下所示代碼爲定義一個靜態嵌套類:
public class StaticTest {
private static String name = "woobo";
private String num = "X001";
static class Person { // 靜態內部類可以用public,protected,private修飾
// 靜態內部類中可以定義靜態或者非靜態的成員
private String address = "China";
private static String x = "as";
public String mail = "[email protected]";// 內部類公有成員
public void display() {
// System.out.println(num);//不能直接訪問外部類的非靜態成員
// 靜態內部類不能訪問外部類的非靜態成員(包括非靜態變量和非靜態方法)
System.out.println(name);// 只能直接訪問外部類的靜態成員
// 靜態內部類只能訪問外部類的靜態成員(包括靜態變量和靜態方法)
System.out.println("Inner " + address);// 訪問本內部類成員。
}
}
public void printInfo() {
Person person = new Person();
// 外部類訪問內部類的非靜態成員:實例化內部類即可
person.display();
// System.out.println(mail);//不可訪問
// System.out.println(address);//不可訪問
System.out.println(person.address);// 可以訪問內部類的私有成員
System.out.println(Person.x);// 外部類訪問內部類的靜態成員:內部類.靜態成員
System.out.println(person.mail);// 可以訪問內部類的公有成員
}
public static void main(String[] args) {
StaticTest staticTest = new StaticTest();
staticTest.printInfo();
}
}
總結:
1. 靜態內部類可以有靜態成員(方法,屬性),而非靜態內部類則不能有靜態成員(方法,屬性)。
2. 靜態內部類只能夠訪問外部類的靜態成員,而非靜態內部類則可以訪問外部類的所有成員(方法,屬性)。
3. 實例化一個非靜態的內部類的方法:
a. 先生成一個外部類對象實例
OutClassTest oc1 = new OutClassTest();
b. 通過外部類的對象實例生成內部類對象
OutClassTest.InnerClass no_static_inner = oc1.new InnerClass();
4. 實例化一個靜態內部類的方法:
a. 不依賴於外部類的實例,直接實例化內部類對象
OutClassTest.InnerStaticClass inner = new OutClassTest.InnerStaticClass();
b. 調用內部靜態類的方法或靜態變量,通過類名直接調用
OutClassTest.InnerStaticClass.static_value
OutClassTest.InnerStaticClass.getMessage()
最後,我再告訴大家,接口雖然不能有任何實現,但內部類(無論是靜態的還是非靜態的內部類)卻可以作爲接口的一部分,例如:
public interface TestInterface {
void testMethod();
static class TestInnerClass implements TestInterface {// 並不是非要實現TestInterface,這裏可以做任何事情。
@Override
public void testMethod() {
System.out.println("測試");
}
}
}
class Test {
public static void main(String[] args) {
TestInnerClass testClass = new TestInterface.TestInnerClass();
testClass.testMethod();
}
}