概述
最近學(xué)習(xí)python,發(fā)現(xiàn)python是支持多繼承的,這讓我想起Java是通過內(nèi)部類實(shí)現(xiàn)的這套機(jī)制。這篇文章不是講如何通過內(nèi)部類實(shí)現(xiàn)多繼承,而是總結(jié)一下內(nèi)部類的類型和使用方法。
Java內(nèi)部類分為:
內(nèi)部類在Android源碼中被大量的使用,先介紹一下這四種內(nèi)部類的共同點(diǎn):
接下來,分別介紹一下這幾種內(nèi)部類。
非靜態(tài)內(nèi)部類
當(dāng)一個(gè)類作為另一個(gè)類的非靜態(tài)成員時(shí),則這個(gè)類就是一個(gè)非靜態(tài)內(nèi)部類。
創(chuàng)建非靜態(tài)內(nèi)部類的示例代碼如下:
class OutClass { class InnerClass {}}
當(dāng)我們用javac去編譯的時(shí)候,發(fā)現(xiàn)生成了兩個(gè).class文件:OutClass.class和OutClass$InnerClass.class。如下圖所示:
從外部類的非靜態(tài)方法中實(shí)例化內(nèi)部類
在外部類中訪問內(nèi)部類是很容易的,直接創(chuàng)建內(nèi)部類對(duì)象,然后通過對(duì)象實(shí)例調(diào)用類內(nèi)的方法即可。示例代碼如下:
public class OutClass { private static int a = 0; public void makeInner() { InnerClass inClass = new InnerClass(); inClass.seeOuter(); } public static void main(String[] args) { OutClass oClass = new OutClass(); oClass.makeInner(); } class InnerClass { public void seeOuter() { System.out.println(a); a++; } }}
0
從外部類的靜態(tài)方法中實(shí)例化內(nèi)部類
在外部類中訪問內(nèi)部類是比較簡(jiǎn)單的,可以直接new出內(nèi)部類對(duì)象,但是如果想在外部類的外部使用內(nèi)部類,接不能直接new內(nèi)部類名的方式了,而是需要如下方式:
OutClass.InnerClass innerClass = new OutClass().new InnerClass();
也就是說,在外部調(diào)用非靜態(tài)內(nèi)部類,需要先實(shí)例化外部類,然后通過外部類對(duì)象再去實(shí)例化內(nèi)部類。示例代碼如下:
public class OutClass { private static int a = 0; public void makeInner() { InnerClass inClass = new InnerClass(); inClass.seeOuter(); } public static void main(String[] args) { OutClass oClass = new OutClass(); oClass.makeInner(); OutClass.InnerClass innerClass = new OutClass().new InnerClass(); innerClass.seeOuter(); } class InnerClass { public void seeOuter() { System.out.println(a); a++; } }}
運(yùn)行結(jié)果:
01
內(nèi)部類的this引用
普通的類可以使用this引用當(dāng)前的對(duì)象,內(nèi)部類也是如此。但是假若內(nèi)部類想引用外部類當(dāng)前的對(duì)象呢?可以使用如下方式:
外部類名.this
示例代碼如下:
public class OutClass { private static int a = 0; public void makeInner() { InnerClass inClass = new InnerClass(); inClass.seeOuter(); } public static void main(String[] args) { OutClass oClass = new OutClass(); oClass.makeInner(); OutClass.InnerClass innerClass = new OutClass().new InnerClass(); innerClass.seeOuter(); } class InnerClass { public void seeOuter() { System.out.println(this); System.out.println(OutClass.this); } }}
靜態(tài)內(nèi)部類
上面介紹了非靜態(tài)內(nèi)部類,接下來我們學(xué)習(xí)神馬是靜態(tài)內(nèi)部類。
靜態(tài)內(nèi)部類就是在外部類中扮演一個(gè)靜態(tài)成員的角色,創(chuàng)建靜態(tài)內(nèi)部類和創(chuàng)建非靜態(tài)內(nèi)部類的形式很相似,只是class前面多了一個(gè)static修飾符。
注意,外部類是不可能使用static修飾符進(jìn)行修飾的。
示例代碼如下:
class OutClass { static class InnerClass { }}
用javac命令編譯一下,可以看到一樣都是有兩個(gè).class文件,如下圖所示:
從外部類的非靜態(tài)方法中實(shí)例化靜態(tài)內(nèi)部類
從外部類中訪問靜態(tài)內(nèi)部類,和在外部類中訪問非靜態(tài)內(nèi)部類是一樣的。但是,需要注意一點(diǎn),此時(shí)靜態(tài)內(nèi)部類只能訪問外部類的靜態(tài)成員,無法訪問非靜態(tài)成員了。
示例代碼如下:
public class OutClass { private static int a = 0; private int b = 1; public void makeInner() { InnerClass inClass = new InnerClass(); inClass.seeOuter(); } public static void main(String[] args) { OutClass oClass = new OutClass(); oClass.makeInner(); } static class InnerClass { public void seeOuter() { System.out.println(this); System.out.println(a); // System.out.println(b); } }}
執(zhí)行結(jié)果如下:
OutClass$InnerClass@79a3400
從外部類靜態(tài)方法中實(shí)例化靜態(tài)內(nèi)部類
注意:
因?yàn)殪o態(tài)內(nèi)部類是外部類的靜態(tài)成員,而靜態(tài)成員是跟類綁定,而不是跟類實(shí)例化的對(duì)象綁定。所以,在外部類的靜態(tài)方法中實(shí)例化內(nèi)部類,是不需要先實(shí)例化外部類的。
示例代碼如下:
public class OutClass { private static int a = 0; private int b = 1; public void makeInner() { InnerClass inClass = new InnerClass(); inClass.seeOuter(); } public static void main(String[] args) { OutClass oClass = new OutClass(); oClass.makeInner(); OutClass.InnerClass inClass = new OutClass.InnerClass(); inClass.seeOuter(); } static class InnerClass { public void seeOuter() { System.out.println(this); System.out.println(a); // System.out.println(b); } }}
匿名內(nèi)部類
匿名內(nèi)部類在Android應(yīng)用開發(fā)中簡(jiǎn)直是泛濫,各種listener對(duì)象的實(shí)現(xiàn)很多都是通過匿名內(nèi)部類。
匿名內(nèi)部類從名字上就可以知道這是代表沒有類名的內(nèi)部類,通常用來簡(jiǎn)化代碼。
相信寫Java的同學(xué)都使用過線程,那Thread的時(shí)候我們可以傳一個(gè)Runnable對(duì)象,也可以傳一個(gè)匿名內(nèi)部類。示例代碼如下:
public class OutClass { public void testAnonymousClass() { Thread t = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 10; i ++) { System.out.println(i); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } }); t.start(); System.out.println("another thread is running..."); } public static void main(String[] args) { OutClass oClass = new OutClass(); oClass.testAnonymousClass(); }}
執(zhí)行結(jié)果如下:
another thread is running...
新聞熱點(diǎn)
疑難解答
圖片精選