Java巢狀類(NestedClasses)總結
Nested Classes定義
在java語言規範裡面,巢狀類(Nested Classes)定義是:
A nested class is any class whose declaration occurs within the body of another class or interface. A top level class is a class that is not a nested class.
說的簡單一點,就是定義在類裡面的類。一般把定義內部類的外圍類成為包裝類(enclosing class)或者外部類
巢狀類分類
根據nested class定義的地方,可以分為member nested class,local nested class , anonymous nested class
member nested class(成員巢狀類) :成員巢狀類 作為 enclosing class 的成員定義的,成員巢狀類有enclosing class屬性
local nested class (區域性巢狀類): 區域性巢狀類定義在 enclosing class 的方法裡面,區域性巢狀類有enclosing class 屬性和enclosing method 屬性
anonymous nested class(匿名巢狀類):匿名巢狀類沒有顯示的定義一個類,直接通過new 的方法建立類的例項。一般回撥模式情況下使用的比較多
member nested class 可以使用public,private,protected訪問控制符,也可以用static,final關鍵字
local nested class 可以使用final關鍵字
anonymous nested class 不使用任何關鍵字和訪問控制符
見下面的程式碼
public class EnclosingClass
public static final class NestedMemberClass
}
public void nestedLocalClass()
final class NestedLocalClass
}
}
public void nestedAnonymousClass()
new Runnable()
@Override
public void run()
}
};
}
} |
如果你想學習java可以來這個群,首先是二二零,中間是一四二,最後是九零六,裡面有大量的學習資料可以下載
在大多數情況下,一般把nested classes 分為兩種:
Static Nested Classes(靜態巢狀類): 就是用static修飾的成員巢狀類
InnerClass:靜態巢狀類之外所有的巢狀類的總稱,也就是沒有用static定義的nested classes,Inner Classes 不能定義為static,不能有static方法和static初始化語句塊。在JLS(java語言規範)裡面是這麼定義的:
An inner class is a nested class that is not explicitly or implicitly declared static. Inner classes may not declare static initializers (§8.7) or member inter- faces
其中Inner Class又可以分為三種:
1 inner member classes :沒有用static 修飾的成員內部類
2 local inner classes : 定義在方法裡面的內部類,方法可以是static的也可以是非static的,也可以是構造器方法。
3 anonymous inner classes :定義在方法裡面匿名類,方法可以是static的也可以是非static的
巢狀類訪問規則
Static Nested Classes 以及 inner classes 有一些限制規則,下面介紹一下這些規則。
- Static Nested Classes訪問規則
用Static修飾的Nested Classes,只能訪問外部類的非static變數。對於public 的 static Nested Classes 可以用 new 外部類.內部類()的方式直接建立。而預設的static Nested Classes 可以在同一包名下,用 new 外部類.內部類()的方式建立。其實和外部類的方式差不多。靜態成員類可以使用訪問控制符,可以使用static修飾,可以是abstract抽象類
public class StaticNestedClass
//
private int i 0 ;
//
public static int j 0 ;
//
private final int k 0 ;
//
private static final int m 0 ;
//
public static class PublicNestedClass
private void test1()
//
System.out.println(j);
System.out.println(m);
//
}
//
private static void test2()
}
}
//
private static class PrivateNestedClass
}
} |
下面的例子演示了static Nested class的建立
public class TestClass
public static void main(String[]
//任何地方都可以建立
StaticNestedClass.PublicNestedClass new StaticNestedClass.PublicNestedClass();
//可以在同一package下建立
StaticNestedClass.DefaultNestedClass new StaticNestedClass.DefaultNestedClass();
//編譯錯誤,無法訪問內部內
//StaticNestedClass.PrivateNestedClass
}
} |
- Inner Class訪問規則
inner member classes(內部成員類) 可以訪問外部類的所有例項屬性,靜態屬性。因為內部成員類持有一個外部物件的引用,內部類的例項可以對外部類的例項屬性進行修改。如果是public的 inner member classes,可以通過 外部類例項.new 內部類()的方式進行建立,當呼叫內部類的構造器的時候,會把當前建立的內部類物件例項中持有的外部物件引用賦值為當前建立內部類的外部類例項。內部成員類可以是使用訪問控制符,可以定義為final,也可以是抽象類。
public class MemberInnerClass
//
public int i 0 ;
//
private static int j 0 ;
//
private final int k 0 ;
//
private static final int m 0 ;
public class PublicMemberInnerClass
//
public void test()
System.out.println(i);
System.out.println(j);
System.out.println(m);
System.out.println(k);
}
public MemberInnerClass
return MemberInnerClass. this ;
}
//
//
}
//
private class PrivateMemberInnerClass
}
//
class DefaultMemberInnerClass
public MemberInnerClass
return MemberInnerClass. this ;
}
}
} |
下面例子演示了內部成員類的建立
public class TestClass
public static void main(String[]
//
MemberInnerClass new MemberInnerClass();
//
MemberInnerClass.PublicMemberInnerClass new PublicMemberInnerClass();
//
MemberInnerClass.DefaultMemberInnerClass new DefaultMemberInnerClass();
//
//
//
//
System.out.println(pmic.getOutterClass()
System.out.println(dmic.getOutterClass()
}
} |
執行程式,列印結果:
true true |
2 local inner classes(區域性類)
區域性類 定義在類方法裡面。這個方法既可以是靜態方法,也可以是例項方法,也可以是構造器方法或者靜態初始化語句塊。
區域性類可以定義在一個static上下文裡面 和 非static上下文裡面。區域性類不能有訪問控制符(private,public,protected修飾),可以是抽象的,也可以定義為final
定義在static上下文(static 欄位初始化,static初始化塊,static方法)裡面的local inner classes 可以訪問類的靜態屬性,如果定義在靜態方法裡面的區域性類,還可以方法裡面定義的final變數。在static上下文定義的區域性類,沒有指向父類例項變數的引用,因為static方法不屬於類的例項,屬於類本身。而且區域性類不能在外部進行建立,只能在方法呼叫的時候進行建立
public class LocalInnerClass
//
private int i 0 ;
//
public static int j 0 ;
//
private final int k 0 ;
//
private static final int m 0 ;
public static void test()
final int a 0 ;
int b 0 ;
//
abstract class LocalStaticInnerClass
//
//
private int d 0 ;
public LocalStaticInnerClass()
//
System.out.println(a);
//
//
//
//
//
System.out.println(j);
System.out.println(m);
}
//
//
}
}
public void test2()
final int a 0 ;
int b 0 ;
final class LocalNonStaticInnerClass{
public LocalNonStaticInnerClass()
//定義在非static上下文的local
System.out.println(i);
System.out.println(k);
System.out.println(j);
System.out.println(m);
}
}
}
} |
3 anonymous inner classes (匿名類)也是定義在方法裡面,匿名類和區域性類訪問規則一樣,只不過內部類顯式的定義了一個類,然後通過new的方式建立這個區域性類例項,而匿名類直接new一個類例項,沒有定義這個類。匿名類最常見的方式就是回撥模式的使用,通過預設實現一個介面建立一個匿名類然後,然後new這個匿名類的例項。
public class AnonymousInnerClass
//訪問規則和區域性類一樣
public void test()
//匿名類實現
new Thread( new Runnable()
@Override
public void run()
}
}).start();
//非匿名類實現
class NoneAnonymousClass implements Runnable{
public void run()
}
}
NoneAnonymousClass new NoneAnonymousClass();
new Thread(t).start();
}
} |
巢狀類的層次
巢狀類是可以有層次的,也就是說巢狀類裡面還是定義類,成為巢狀類中的巢狀類。虛擬機器如何保證巢狀類正確的巢狀層層次?
對於merber class,內部巢狀類的可以表示為 A$B 其中A為外部類,B為內部成員類 ,如果B裡面又有成員為C的巢狀類,那麼C就可以表示為A$B$C,如果A定義了兩個同名member class,那麼編譯器就會報錯。如果B裡面又包含了為名B的nested class,則編譯器會報錯.
對於local inner Class,區域性類可以表示為A$1B的方式,其中A為外部類,B為第一個區域性類 如果在不同的方法裡面定義了同名的區域性類B,編譯器是可以編譯通過的,那麼定義的第二個區域性類B可以表示為A$2B,如果在同一個方法裡面同定義兩個相同的區域性類B,那麼編譯錯是要報錯的。如果B裡面又定義了同名的成員類,則可以表示為A$1B$B。
對於anonymous inner classes,匿名類可以表示為A$1的方式,代表程式裡面有一個匿名類。如果有N個,可以表示為A$N的方式(N為自然數).
看看下面的例子
public class NestedClassLevel
class A
//
//
public void test()
class B
}
}
}
//可以在繼續定義B
class B
public void test(){
//可以無限定義匿名類
new Runnable()
public void run()
//可以無限定義匿名類
new Runnable()
public void run()
}
};
}
};
}
}
//
//
public void test()
//
class A
public void test()
//可以有同名的區域性類B和成員類B
class B
public void test()
}
}
//區域性類A裡面不能在定義A
//class
}
}
//可以有同名的區域性類B和成員類B
class B
}
}
} |
對於定義在非static上下文裡面的nested類層次,比如A$B$1C ,則最內層的巢狀類C有一個指向B例項的引用,B有一個指向A例項的引用,最終最內層的巢狀類可以訪問A中的屬性可以方法,一般把B成為A的直接巢狀類。但是A不可以訪問B或者C中屬性或者方法。
nested interface
由於interface預設是定義為一個 public static的特殊類,所以interface可以直接作為 static member class。可以通過A.B的方式進行訪問。
nested class的應用
在java提供的基本類庫裡面,大量使用nested classes。比如我們知道的map類。其中 Map類裡面有一個定義了Entry類abstract inner class。所以我們在遍歷map的時候,一般使用
for (Map.Entry entry:map.entrySet()){
}
總結:nested類是java裡面比較複雜的一個概念,必須詳細瞭解jvm中對於巢狀類的實現以及java編譯器對巢狀類的處理才可以深入瞭解巢狀類細節。
相關文章
- Java進階07 巢狀類Java巢狀
- Android:巢狀滑動總結Android巢狀
- Java | 靜態巢狀類(Static Nested Class)Java巢狀
- 巢狀類遞迴巢狀遞迴
- Android筆記之Kotlin、Java的內部類?巢狀類?Android筆記KotlinJava巢狀
- 類與介面(三)java中的介面與巢狀介面Java巢狀
- python-if elif巢狀結構Python巢狀
- Java 程式碼規範if巢狀Java巢狀
- java定時任務巢狀Java巢狀
- 常用Java集合類總結Java
- C++ 巢狀類簡單測試C++巢狀
- Java總結-抽象類與介面Java抽象
- Java集合類學習總結Java
- Java 常用類總結(SE基礎)Java
- Java類載入知識總結Java
- Java類載入機制總結Java
- Java類和物件知識點總結Java物件
- 列表巢狀操作巢狀
- vue路由巢狀Vue路由巢狀
- [20190506]檢視巢狀與繫結變數.txt巢狀變數
- 【java】【集合】去除ArrayList中的元素、ArrayList巢狀ArrayListJava巢狀
- Java經典常用類總結(必須掌握!)Java
- java面試題總結-詳細分類Java面試題
- Blazor巢狀傳遞Blazor巢狀
- 展開巢狀列表巢狀
- vue(19)巢狀路由Vue巢狀路由
- Locust 任務巢狀巢狀
- Oracle 巢狀表(轉)Oracle巢狀
- 巢狀子查詢巢狀
- SCSS 巢狀屬性CSS巢狀
- SCSS 巢狀規則CSS巢狀
- java中如何將巢狀迴圈效能提高500倍Java巢狀
- Java JDK11基於巢狀的訪問控制JavaJDK巢狀
- MySQL Join原理分析(緩衝塊巢狀與索引巢狀迴圈)MySql巢狀索引
- PHP中的無限級分類、無限巢狀評論PHP巢狀
- Java集合類操作最佳化經驗總結Java
- Java中atomic包中的原子操作類總結Java
- 碎片化學習Java(二十)Java for迴圈巢狀輸出指定圖案Java巢狀
- Vue中的巢狀路由Vue巢狀路由