Java內部類(inner Class)和巢狀類(static inner Class)也就是靜態內部類的區別
阿新 • • 發佈:2018-12-26
內部類和靜態類有著本質的區別,有點類似普通成員變數和靜態成員變數的區別。
.
內部類可以看成是外部類的普通成員變數,這個成員變數可以使用外部類的屬性(靜態和非靜態),可以呼叫外部類的方法(靜態和非靜態),而且內部類還持有外部類物件作為其自身的一個屬性,這個屬性的名稱叫 this$0,可以使用反射獲取外部類物件。內部類物件在其他類中不能使用建構函式直接new得到,因為內部類物件類似外部類的成員變數,外部類不存在時,內部屬性自然不能生成。內部類持有外部類物件的最好例項就是容器類的Iterator物件,通過容器類的iterator()方法得到Iterator物件,然後通過Iterator物件就能遍歷容器,就是因為Iterator物件持有外部物件也就是容器物件的例項,大部分容器均有一個內部類實現了Iterator介面,實現自己的遍歷邏輯。
.
巢狀類可以看成是外部類的靜態成員,只能使用外部類的靜態屬性和靜態方法。巢狀類是獨立於外部類存在的,也就是其他類可以通過呼叫巢狀類的建構函式來獲取巢狀類例項。巢狀類不持有外部類物件例項,巢狀類可以看成是另外一個獨立的類。很多情況是巢狀類僅僅在外部類裡使用,使用巢狀類對外部類的幾個屬性或者一些函式做一個封裝,便於外部類的邏輯實現 , 所以其修飾符很多時候定義為private static class。
.
內部類和巢狀類的類名均是:外部類名稱+$
可以通過外部類的Class.getDeclaredClasses()方法獲取所有定義的內部類和巢狀類。
程式碼示例:
public class TopLevelClass {
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public InnerClass getInnerClass(){
return new InnerClass();
}
public NestedClass getNestedClass(){
return new NestedClass();
}
public static void print(){
System.out.println("呼叫靜態方法");
}
/**
* 內部類
*/
public class InnerClass {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String toString(){
//內部類可以使用外部類的屬性和方法
return id + name;
}
}
/**
* 巢狀類,靜態內部類
*/
public static class NestedClass {
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void print(){
//巢狀類智慧使用外部類的靜態成員及方法
TopLevelClass.print();
}
}
}
程式碼測試:
public class InnerClassTest {
@Test
public void getInnerClass(){
//InnerClass is = new InnerClass(); 會報錯
InnerClass is = new TopLevelClass().getInnerClass();
}
@Test
public void getNestedClass(){
NestedClass ns = new NestedClass();
ns = new TopLevelClass().getNestedClass();
}
@Test
public void testInnerClassName() {
//獲取所有的內部類及巢狀類
Class<?>[] classes = TopLevelClass.class.getDeclaredClasses();
for (Class<?> clazz : classes) {
//內部類和巢狀類都屬於成員類
System.out.println(clazz.isMemberClass());
System.out.println(
"Class.Name = " + clazz.getName() + ", Class.SimpleName = " + clazz.getSimpleName() + ", Class.Package = " + clazz.getPackage().getName());
}
System.out.println(TopLevelClass.class.isMemberClass());
}
@Test
public void getOutterClassInstance() throws NoSuchFieldException, IllegalAccessException {
TopLevelClass tps = new TopLevelClass();
InnerClass is = tps.getInnerClass();
Field filed = is.getClass().getDeclaredField("this$0");
//獲取內部類物件持有的外部類例項
TopLevelClass innerTps = (TopLevelClass)filed.get(is);
//返回true,他們是同一個物件
System.out.println(tps == innerTps);
}
}