您好,登錄后才能下訂單哦!
這篇文章將為大家詳細(xì)講解有關(guān)Java開發(fā)崗位面試被問到嵌套類該怎么回答,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
靜態(tài)內(nèi)部類(靜態(tài)嵌套類/靜態(tài)成員類/靜態(tài)類)
內(nèi)部類(非靜態(tài)嵌套類)
內(nèi)部成員類
本地內(nèi)部類
匿名內(nèi)部類
嵌套接口
重要的結(jié)論:如果一個類被聲明為static(即static修飾class),只有一種情況,該類是靜態(tài)內(nèi)部類。
沒有限制,可以聲明各種類型的類,變量,方法和靜態(tài)代碼塊,細(xì)分為:
類:
枚舉類
靜態(tài)內(nèi)部類
內(nèi)部類
接口
變量:
靜態(tài)變量
實例變量
方法:
靜態(tài)方法
實例方法
靜態(tài)代碼塊
靜態(tài)內(nèi)部類可以訪問外圍類的任何成員,包括外圍類中聲明為private的成員,分為:
外圍類的靜態(tài)變量和方法(含私有):直接訪問
外圍類的實例變量和方法(含私有):通過外圍類的實例對象進(jìn)行訪問
靜態(tài)內(nèi)部類類似類的靜態(tài)變量,不需要依賴外圍類的實例對象而存在,可以看作是頂層類,可以直接通過外圍類來訪問。
在繼承方面,靜態(tài)內(nèi)部類與外圍類沒什么分別,在訪問權(quán)限允許的情況下:任何類都可以繼承靜態(tài)內(nèi)部類,靜態(tài)內(nèi)部類也可以繼承任何類(類沒有聲明為final)或?qū)崿F(xiàn)任何接口。
public class OuterClass { // 靜態(tài)變量 final static boolean FLAG_VALUE = true; private static String name = "Outer Class"; // 實例變量 private int age; // 靜態(tài)方法 private static String getName() { return name; } // 實例方法 private void setAge(int age) { this.age = age; } // 靜態(tài)內(nèi)部類 public static class StaticInner { // 聲明靜態(tài)變量 final static int x = 1; static int y = 2; // 聲明實例變量 int a; // 聲明靜態(tài)代碼塊 static { } // 聲明枚舉類 enum InnerEnum { } // 聲明靜態(tài)內(nèi)部類 static class Inner2 { } // 聲明接口 interface Inner3 { } // 聲明內(nèi)部類 class Inner4 { } // 聲明靜態(tài)方法 static void OperateStatic() { System.out.println("靜態(tài)內(nèi)部類直接訪問外圍類的靜態(tài)變量:name = " + name + ", FLAG_VALUE = " + FLAG_VALUE); System.out.println("靜態(tài)內(nèi)部類直接訪問外圍類的靜態(tài)方法:getName : " + getName()); // 靜態(tài)內(nèi)部類不能直接訪問外圍類的實例變量和方法 //age = 30; //setAge(30); // 通過聲明外圍類對象,訪問外圍類對象的實例變量和方法 OuterClass outerClass = new OuterClass(); outerClass.age = 30; outerClass.setAge(30); }//加入Java開發(fā)交流君樣:756584822一起吹水聊天 // 聲明實例方法 void operate() { System.out.println("靜態(tài)內(nèi)部類直接訪問外圍類的靜態(tài)變量:name = " + name + ", FLAG_VALUE = " + FLAG_VALUE); System.out.println("靜態(tài)內(nèi)部類直接訪問外圍類的靜態(tài)方法:getName : " + getName()); // 靜態(tài)內(nèi)部類不能直接訪問外圍類的實例變量和方法 //age = 30; //setAge(30); // 通過聲明外圍類對象,訪問外圍類對象的實例變量和方法 OuterClass outerClass = new OuterClass(); outerClass.age = 30; outerClass.setAge(30); } } }
內(nèi)部成員類
本地內(nèi)部類(本地類/局部類)
匿名內(nèi)部類(匿名類)
內(nèi)部類可以聲明實例變量,實例方法,final類型的靜態(tài)變量。
內(nèi)部類不可以聲明靜態(tài)成員:包括靜態(tài)變量,靜態(tài)方法,靜態(tài)內(nèi)部類,嵌套接口,靜態(tài)初始化塊。
細(xì)分為:
類:
只能聲明內(nèi)部類
不能聲明枚舉類,靜態(tài)內(nèi)部類,接口
變量:
只能聲明實例變量,final類型靜態(tài)變量
不能聲明靜態(tài)變量
方法:
只能聲明實例方法
不能聲明靜態(tài)方法
不能聲明靜態(tài)代碼塊
沒有限制,外圍類的所有變量和方法(含私有)都可以直接訪問。
public class OuterClass { // 靜態(tài)變量 final static boolean FLAG_VALUE = true; private static String name = "Outer Class"; // 實例變量 private int age; // 靜態(tài)方法 private static String getName() { return name; } // 實例方法 private int getAge() { return age; } // 內(nèi)部類 public class Inner { // 內(nèi)部類不能聲明靜態(tài)變量 //private static String innerName = "Inner Class"; // 內(nèi)部類只能聲明實例變量和final類型靜態(tài)變量 private int a; final static int x = 1; // 內(nèi)部類不能聲明靜態(tài)代碼塊,枚舉類,靜態(tài)內(nèi)部類,接口(枚舉類型和接口類型總是靜態(tài)的) //static { } //enum InnerEnum { } //static class Inner2 { } //interface Inner3 { } // 內(nèi)部類聲明內(nèi)部類 class Inner4 { } // 內(nèi)部類不能聲明靜態(tài)方法 //static void OperateStatic() { } // 內(nèi)部類只能聲明實例方法 void operate() { System.out.println("內(nèi)部類訪問外圍類的靜態(tài)變量:name = " + name); System.out.println("內(nèi)部類訪問外圍類的靜態(tài)final變量:FLAG_VALUE = " + FLAG_VALUE); System.out.println("內(nèi)部類訪問外圍類的實例變量:age = " + (age = 40)); System.out.println("內(nèi)部類訪問外圍類的靜態(tài)方法:getName() = " + getName()); System.out.println("內(nèi)部類訪問外圍類的實例方法:getAge() = " + getAge()); }//加入Java開發(fā)交流君樣:756584822一起吹水聊天 } }
總結(jié): 創(chuàng)建內(nèi)部類對象(調(diào)用內(nèi)部類的構(gòu)造器)時,編譯器會隱式地在內(nèi)部類中聲明一個final的外圍類類型的成員變量,然后將外圍類的對象,通過內(nèi)部類的構(gòu)造器傳遞給該final成員變量,用來將內(nèi)部類對象綁定到外圍類對象。
public class Outer { public class Inner { // 編譯器自動隱式生成的外圍類類型的成員變量 final Outer this$0; // 通過內(nèi)部類構(gòu)造器將外圍類的對象傳遞給this$0成員變量,實現(xiàn)內(nèi)部類與外圍類對象的綁定 public Inner(Outer outer) { this$0 = outer; super(); } } }
創(chuàng)建內(nèi)部類對象,如下:
Outer outer = new Outer(); Outer.Inner inner = outer.new Inner();
創(chuàng)建內(nèi)部類對象時,系統(tǒng)會自動將外圍類的對象(outer)作為參數(shù)傳入內(nèi)部類的構(gòu)造器中,可認(rèn)為是下面的方式:
Outer.Inner inner = outer.new Inner(outer);
在訪問權(quán)限允許的情況下:內(nèi)部類可以繼承任何類,也可以由任何類繼承。
問:那內(nèi)部類與靜態(tài)內(nèi)部類在繼承方面有什么區(qū)別呢?
答:內(nèi)部類的對象總是要依賴于外部對象,因此一個類A繼承了一個內(nèi)部類,則類A也必須要與內(nèi)部類的外圍類對象相綁定,否則產(chǎn)生編譯錯誤。
1.反例:產(chǎn)生編譯錯誤
public class A extends Outer.Inner { } class Outer { class Inner { } }
2.錯誤原因:想要創(chuàng)建A類對象,即A a = new A(); 會調(diào)用A類構(gòu)造器,A類繼承內(nèi)部類(Outer.Inner),則會調(diào)用內(nèi)部類的構(gòu)造器
這時沒有有效的外圍類對象,則無法實現(xiàn)內(nèi)部類對象與外圍類對象的綁定,產(chǎn)生編譯錯誤。
3.修正
方法一:在A類構(gòu)造器中傳遞一個外圍類的引用,通過外圍類對象來調(diào)用內(nèi)部類的構(gòu)造器,就相當(dāng)于將外圍類的對象傳遞給了內(nèi)部類的構(gòu)造器,實現(xiàn)了內(nèi)部類對象與外圍類對象的綁定。
public class A extends Outer.Inner { public A(Outer outer) { outer.super(); } } class Outer { class Inner { } }
方法二:外部類繼承外部類,內(nèi)部類繼承內(nèi)部類
public class A extends Outer { class InnerA extends Outer.Inner { } } class Outer { class Inner { } }
創(chuàng)建A類的內(nèi)部類InnerA對象:
A a = new A(); A.InnerA innerA = a.new InnerA();
創(chuàng)建內(nèi)部類A.InnerA對象時,需要綁定外圍對象,a引用就是外圍類的對象,
內(nèi)部類A.InnerA繼承了另外一個內(nèi)部類Outer.Inner,在A.InnerA調(diào)用父類構(gòu)造器時,也需要傳遞父類的外圍類(Outer)對象,
A類繼承了Outer類,因為子類的對像可以當(dāng)作父類的對象來使用,因此a引用也是另一個內(nèi)部類Outer.Inner的外圍對象。
本地內(nèi)部類:就是在方法,構(gòu)造器,初始化塊中聲明的類。
本地內(nèi)部類不是類的成員,從結(jié)構(gòu)上類似一個局部變量,因此不能使用訪問修飾符(public,protected,private),也不能使用static修飾。
public class LocalInnerDemo { private int x = 100; // 1.本地內(nèi)部類聲明在實例初始化塊中 { class Local1 { } } // 2.本地內(nèi)部類聲明在靜態(tài)初始化塊中 static { class Local2 { } } // 3.本地內(nèi)部類聲明在構(gòu)造器中 public LocalInnerDemo() { int y = 2; final int z = 3; class Local3 { int a = x; int b = y; int c = z; } }//加入Java開發(fā)交流君樣:756584822一起吹水聊天 // 4.本地內(nèi)部類聲明在實例方法中 public T1 method1() { // 使用本地內(nèi)部類實現(xiàn)某個接口,然后以接口形式返回 class Local4 implements T1 { @Override public void operate() { System.out.println("Start to operate."); } } return new Local4(); } // 5.本地內(nèi)部類聲明在靜態(tài)方法中 public static T1 method2() { class Local5 implements T1 { @Override public void operate() { System.out.println("Start to operate."); } } return new Local5(); } } interface T1 { void operate(); }
問:本地內(nèi)部類聲明在實例環(huán)境(實例方法,構(gòu)造器,實例初始化塊)和靜態(tài)環(huán)境中有什么區(qū)別呢?
答:實例環(huán)境:本地內(nèi)部類需要與外圍類綁定,即會在類中隱式生成一個final的引用。
靜態(tài)環(huán)境:本地內(nèi)部類不需要與外圍類綁定。
嵌套接口:就是在類或者接口中聲明的接口。
不管聲明在類中,還是接口中,嵌套接口永遠(yuǎn)都是靜態(tài)的。
當(dāng)類實現(xiàn)了某個接口時,不需要實現(xiàn)嵌套接口的方法。
關(guān)于“Java開發(fā)崗位面試被問到嵌套類該怎么回答”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,使各位可以學(xué)到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。