嵌套類分為兩類:靜態(tài)和非靜態(tài)苛聘。被聲明static的嵌套類稱為靜態(tài)嵌套類。非靜態(tài)嵌套類稱為內(nèi)部類纲菌。
內(nèi)部類有兩種特殊的內(nèi)部類: 本地類和 匿名類焕议。
為什么使用嵌套類:
- 這是一種邏輯分組的方法宝磨,它只在一個(gè)地方使用:如果一個(gè)類只對另一個(gè)類有用,那么將它嵌入該類并將它們保持在一起是合乎邏輯的盅安。嵌套這樣的“幫助類”使得它們的包更加簡化唤锉。
- 它增加了封裝:考慮兩個(gè)頂級(jí)類A和B,其中B需要訪問否則將被聲明的A成員private别瞭。通過在類A中隱藏類B腌紧,可以將A的成員聲明為私有,并且B可以訪問它們畜隶。另外壁肋,B本身可以被外界隱藏起來号胚。
- 它可以導(dǎo)致更易讀和可維護(hù)的代碼:在頂級(jí)類中嵌套小類會(huì)使代碼更接近它的使用位置。
1.靜態(tài)嵌套類
與類方法和變量一樣浸遗,靜態(tài)嵌套類與其外部類相關(guān)聯(lián)猫胁。像靜態(tài)類方法一樣,靜態(tài)嵌套類不能直接引用其封閉類中定義的實(shí)例變量或方法:它只能通過對象引用來使用它們跛锌。
注意: 靜態(tài)嵌套類與其外部類(和其他類)的實(shí)例成員交互弃秆,就像任何其他頂級(jí)類一樣。實(shí)際上髓帽,為了方便打包菠赚,靜態(tài)嵌套類在行為上是嵌套在另一個(gè)頂級(jí)類中的頂級(jí)類。
public class OuterClass {
static class StaticClass{
public void test(){
System.out.println("static class test");
}
}
public static void main(String[] args) {
OuterClass.StaticClass t = new OuterClass.StaticClass();
t.test();
}
}
2.內(nèi)部類
與實(shí)例方法和變量一樣郑藏,內(nèi)部類與其包含類的實(shí)例關(guān)聯(lián)衡查,并可直接訪問該對象的方法和字段。另外必盖,因?yàn)閮?nèi)部類與一個(gè)實(shí)例相關(guān)聯(lián)拌牲,所以它不能自己定義任何靜態(tài)成員。
一個(gè)實(shí)例InnerClass只能存在于一個(gè)實(shí)例中歌粥,OuterClass并且可以直接訪問其封裝實(shí)例的方法和字段塌忽。
要實(shí)例化一個(gè)內(nèi)部類,你必須首先實(shí)例化外部類失驶。然后土居,使用以下語法在外部對象內(nèi)創(chuàng)建內(nèi)部對象:
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
序列化
內(nèi)部類的序列化,包括 本地和 匿名類嬉探,強(qiáng)烈不鼓勵(lì)装盯。當(dāng)Java編譯器編譯某些結(jié)構(gòu)(如內(nèi)部類)時(shí),它會(huì)創(chuàng)建合成結(jié)構(gòu) ; 這些是在源代碼中沒有相應(yīng)構(gòu)造的類甲馋,方法,字段和其他構(gòu)造迄损。合成結(jié)構(gòu)使Java編譯器能夠在不改變JVM的情況下實(shí)現(xiàn)新的Java語言功能定躏。但是,合成結(jié)構(gòu)可以在不同的Java編譯器實(shí)現(xiàn)中有所不同芹敌,這意味著.class
文件也可以在不同的實(shí)現(xiàn)中有所不同痊远。因此,如果序列化內(nèi)部類氏捞,然后使用不同的JRE實(shí)現(xiàn)對其進(jìn)行反序列化碧聪,則可能會(huì)遇到兼容性問題
2.1 普通內(nèi)部類
public class OuterClass {
public String o = "outer";
private InnerClass inner = new InnerClass();
public void test(){
System.out.println("outer class test: "+inner.i);//inner
}
//內(nèi)部類
class InnerClass{
public String i = "inner";
public void test(String i){
System.out.println("inner class test: "+i);//test_i
System.out.println("inner class test: "+this.i);//inner
System.out.println("inner class test: "+o);//outer
System.out.println("inner class test: "+OuterClass.this.o);//outer
}
}
public static void main(String[] args) {
OuterClass o = new OuterClass();
o.test();
OuterClass.InnerClass i = o.new InnerClass();
i.test("test_i");
}
}
2.2 本地類
本地類是在塊中定義的類,它是平衡花括號(hào)之間的一組零個(gè)或多個(gè)語句液茎。您通常會(huì)在方法的主體中找到定義的本地類逞姿。
- 一個(gè)本地類可以訪問其封閉類的成員辞嗡。
- 本地類可以訪問局部變量。但是滞造,本地類只能訪問聲明為最終的局部變量续室。
public class OuterClass {
public String o = "outer";
public void test(){
System.out.println("outer class test");
final String local = "outer local";
//本地類
class LocalInnerClass{
public String i = "local inner";
public void test(String i){
System.out.println("local inner class test: "+i);//param_i
System.out.println("local inner class test: "+this.i);//local inner
System.out.println("local inner class test: "+o);//outer
System.out.println("local inner class test: "+local);//outer local
System.out.println("local inner class test: "+OuterClass.this.o);//outer
}
}
LocalInnerClass li = new LocalInnerClass();
li.test("param_i");
}
public static void main(String[] args) {
OuterClass o = new OuterClass();
o.test();
}
}
2.3 匿名類
匿名類使您能夠使代碼更加簡潔。它們使您能夠同時(shí)聲明和實(shí)例化一個(gè)類谒养。除了沒有名字之外挺狰,它們就像本地的課程。如果您只需要使用一次本地課程买窟,請使用它們丰泊。
雖然本地類是類聲明,但匿名類是表達(dá)式始绍,這意味著您可以在另一個(gè)表達(dá)式中定義該類瞳购。
public class OuterClass {
public String o = "outer";
interface TestInterface {
public void test();
}
public void test(){
final String local = "outer local";
TestInterface ti = new TestInterface() {
public String t = "anonymous";
@Override
public void test() {
System.out.println("test anonymous class: "+o);
System.out.println("test anonymous class: "+local);
System.out.println("test anonymous class: "+t);
}
};
ti.test();
}
public static void main(String[] args) {
OuterClass o = new OuterClass();
o.test();
}
}
匿名類通常用于圖形用戶界面(GUI)應(yīng)用程序。如添加事件處理疆虚。