當前位置:
首頁 > 知識 > 淺析總結 Java 內部類的一些使用與梳理

淺析總結 Java 內部類的一些使用與梳理



有這篇文章,純屬巧合;那天在使用中突然發現 Java 內部類中還分 static ,說實話平時都在用,但是就是沒有注意到;感覺有必要總結一下。


有必要說一下的是本文純屬淺析,如有補充還請在評論中指出,歡迎總結。


內部類的位置


public class A { class B { } public void pint() { class C { } new C(); } public void pint(boolean b) { if (b) { class D { } new D(); } } }從代碼中可以看出,內部類可以定義到很多地方,常用的是成員變數中(B),方法中也叫局部內部類(C),作用域中(D)

從上面來看似乎沒有用到過在方法中和作用域中的情況啊,這就錯了;再來看看這個:


public interface AInterface { void show(); } public class B { public void show() { class Man implements AInterface { @Override public void show() { } } Man man = new Man(); man.show(); } }其中我們定義了兩個文件,一個文件是一個介面類,一個是B文件;在B類中,的 show()方法中我們使用了局部內部類的方式創建了類 Man ,Man class繼承介面並實現方法,隨後使用該類。


內部類的許可權


為什麼要有內部類的存在?


在我看來類主要的就是封裝、繼承、多態;當然其中的回調思想我認為是很重要的;而內部類的出現就是為了簡化多重繼承的問題;一個A類,並不能繼承多個其他類,但是在使用中又需要使用到其他類的方法,這個時候內部類就發揮作用了;典型的就是事件點擊的回調實現。


那麼內部類的許可權究竟有多大?


至於答案是什麼,代碼上看看就知道了。


public class C { int a = 1; private int b = 2; protected int c = 3; public int d = 4; void a() { System.out.println("A:" + a); } private void b() { System.out.println("B:" + b); } protected void c() { System.out.println("C:" + c); } public void d() { System.out.println("D:" + d); } class D { void show() { int max = a + b + c + d; a(); b(); c(); d(); System.out.println("Max:" + max); } } public static void main(String[] args) { D d = new C().new D(); d.show(); } }運行結果:



淺析總結 Java 內部類的一些使用與梳理


可以看出,內部類 D 對類 C 具有完整的訪問許可權,等於全身脫光了給你看。


那要是反過來呢?



淺析總結 Java 內部類的一些使用與梳理



可見也是完全可行的,也能直接訪問私有屬性 私有方法,在這裡似乎私有的限制已經失效了一般,這個讓我想起了以前看見過一個面試:在 Java 中 private 修飾何時會失效。


這完全是兩個人互相脫光光了啊~


匿名內部類


這個非常常見,特別是在按鈕點擊事件綁定中。


public class D { void initButton() { Button b1 = new Button(); b1.setOnClickListener(new OnClickListener() { @Override public void onClick(Button v) { } }); Button b2 = new Button(); b2.setOnClickListener(new OnClickListener() { @Override public void onClick(Button v) { } }); } }其中的:


new OnClickListener() { @Override public void onClick(Button v) { } }就是匿名內部類的使用方式,OnClickListener 是一個介面類,介面類是無法直接new 一個實例的;這裡也並不是那樣,而是new 了一個其他的類,該類是匿名的,也就是沒有名字,只不過該類實現了 OnClickListener介面類中的方法。

上面的添加回調部分可等同於:


public class D { void initButton1() { Button b1 = new Button(); b1.setOnClickListener(new Listener1()); Button b2 = new Button(); b2.setOnClickListener(new Listener2()); } class Listener1 implements OnClickListener { @Override public void onClick(Button v) { } } class Listener2 implements OnClickListener { @Override public void onClick(Button v) { } } }這裡就是先建立類,繼承自介面;而後賦值到 Button 中。


要說兩者的區別與好處,這個其實看具體的使用情況吧;如果你的按鈕很多,但是為了避免建立太多類;那麼可以建立一個回調類,然後都賦值給所有的按鈕,不過最後就是需要在 onClick方法中進行判斷是那個按鈕進行的點擊。


匿名內部類的使用地方很多;具體的使用應視使用情況而定~


靜態內部類/靜態嵌套類


這個其實並不應該叫做內部類了,因為其並不具備內部類的完全許可權,在使用上與一般的類基本一樣;那為什麼會有這個的存在?


在我看來這個類的存在是為其包括類服務;意思是可以單獨服務,不被外面的類所知曉;如這樣:


public class E { private void show(){ new A(); } private static class A{ } }其中類 A 使用了 static ,所以是靜態嵌套類,在這裡使用private 修飾;那麼該類只能在 E 類中進行實例化;無法在 其他文件中實例化。


這樣的情況使用外面的類能行么?不行吧?也許你會說在 E.java 文件夾中建立 A.java ,並使用protected修飾;但是在同樣的包下,或者繼承的類中同樣能訪問了;這也只是其中一個較為特殊的情況。


我們來看看許可權

public class E { int a1 = 0; private int a2 = 0; protected int a3 = 0; public int a4 = 0; private void show(){ A a =new A(); System.out.print("b1:"+a.b1); System.out.print("b2:"+a.b2); System.out.print("b3:"+a.b3); System.out.print("b4:"+a.b4); } private static class A{ int b1 = 0; private int b2 = 0; protected int b3 = 0; public int b4 = 0; private void print(){ System.out.print("a1:"+a1); System.out.print("a2:"+a2); System.out.print("a3:"+a3); System.out.print("a4:"+a4); } } }在這個中的結果是怎樣?



淺析總結 Java 內部類的一些使用與梳理



從圖片中可以看出,其許可權級別是單方向的;靜態嵌套類 A 對其包含類 E 完全透明;但 E 並不對 A 透明。


再來看看方法:



淺析總結 Java 內部類的一些使用與梳理



可以看出同樣的情況;這個是為什麼呢?為什麼就是多一個 static 的修飾就這麼完全不同?其是很好理解,兩個獨立的類;本來就無法直接使用,必須有引用才能調用其屬性與方法。


我們或許可以這麼調整一下就OK:



淺析總結 Java 內部類的一些使用與梳理


可以看出其中現在並沒有報錯了;能正常運行。


兩者之間的隱藏區別


但是最開始上面的內部類是怎麼回事?難道是鬧鬼了?上面的內部類沒有傳遞引用的啊;為啥加上一個 static 就不行了?


在這裡我們需要看看位元組碼,我們先建立一個簡單的內部類:


public class F { class A{ } }這個夠簡單吧?別說這個都難了;汗~


然後我們找到 class 文件,然後查看位元組碼:



淺析總結 Java 內部類的一些使用與梳理



在這裡分別查看了 F 類的位元組碼和 F$A 類的位元組碼。

其中有這樣的一句: final F this$0; 這句是很重要的一句,這句出現的地方在其內部類中,意思是當你 new 一個內部類的時候就同時傳遞了當前類進去;所以在內部類中能具有當前類的完全許可權,能直接使用所有的東西;就是因為在隱藏情況下已經傳遞了當前類進去。


那麼我們再看看一個簡單的靜態內部類:


public class G { static class A { } }與上面的區別唯一就是在於添加了一個 static 。此時我們看看位元組碼:



淺析總結 Java 內部類的一些使用與梳理



可以看出其中無論是 G 類,還是 G$A 類的初始化中都沒有其他多餘的部分,也沒有進行隱藏的傳遞進去當前類;所以這樣的情況下並不具備訪問許可權,需要我們傳遞引用進去,可以通過介面也可以完全傳遞進去,具體取決於個人。所以加了static類的內部類除了在許可權上比一般的類更加開放(與其包含類)外,與一般的類在使用上是一樣的;所以準確的說應該叫做靜態嵌套類。


初始化的區別


一個類中,同時包含了內部類與靜態內部類,那麼其初始化應該是怎麼樣的呢?


都是直接 new ?還是看看代碼:


public class H { int a = 1; public class A { public void Show() { System.out.print("a:" + a); } } public static class B { public void Show(H h) { System.out.print("a:" + h.a); } } public static void main(String[] args) { H h = new H(); //A a = new A(); A a1 = h.new A(); B b = new B(); //B b1 = h.new B(); B b3 = new H.B(); } }其中注釋了的兩種方式是不允許的方式,也就是無法正常運行。

A 因為有一個隱藏的引用,所以必須是H 的實例才能進行初始化出A 類;而B 類則是因為是在H 類中以靜態方式存在的類,所以需要 new H.B();之所以能直接使用new B(),與該 main 方法在 H 類中有關,因為本來就在 H類中,所以直接使用 H類的靜態屬性或者方法可以不加上:「H.」 在前面。


內部類的繼承


直接繼承的情況:



淺析總結 Java 內部類的一些使用與梳理



可以看出報錯了,為什麼?因為需要傳遞一個 H 類進去,所以我們在繼承的時候需要顯示的指明:


public class I extends H.A{ public I(H h){ h.super(); } }也就是在構造方法中,傳遞一個 H 的引用進去,並調用 H 實例的 super() 方法,才能進行實例化。


使用的話應該這樣:


public static void main(String[] args) { H h = new H(); I i = new I(h); }


而,如果是繼承其靜態嵌套類,則不需要這樣:

public class J extends H.B{ }就這樣就OK。


哎,差不多了~~整個內部類的東西差不多就是這些了,寫了我3個小時42分鐘~汗!!!!


如果有沒有寫到的地方,還請補充~~


不對的地方還請指正~~



淺析總結 Java 內部類的一些使用與梳理


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 IT技術java交流 的精彩文章:

這個Java程序如果你能寫出來,找不到工作來找我!
這些計算機網路知識應該作為程序員的入門基礎
2017年最佳Web前端框架賞鑒
前端初學者最容易忽略的CSS書寫規範和順序
Java的「三生三世」

TAG:IT技術java交流 |

您可能感興趣

各國對Libra的監管梳理及其前景分析
Facebook 投資邏輯梳理
CS求職別忘了高薪稀缺的大數據工程師&常見Search演算法梳理及面試解析
2分鐘梳理JYP邪教boss質疑,「救援派」到底是一種怎樣的存在?
梳理Python基本認識基本類型,Python學習經驗分享
褶子科學家Issey Miyake 的寫意梳理
Google、Facebook還是Amazon?一文梳理各大內容分發平台優缺點
Combino系列有軌電車梳理
頭髮打結難梳理?凱特王妃同款Tangle Teezer美髮梳一梳就順!
Citadis系列有軌電車梳理
《Marketing Management》思維梳理
藍洞與Epic關係梳理 虛幻4引擎背後的交易
大戰三回合 Veeco、中微半導體和SGL和解(附脈絡梳理)
如何閱讀Android項目的源碼,快速梳理程序主線
雷軍宣布小米CC系列,梳理產品線,網友急問note和max呢
手機型號後綴Note、X、Pro,分別代表什麼意思?梳理一下就很簡單
Cytus2劇情梳理Nora篇:身處深淵,天才少女的自我拯救
李光洙官宣承認戀情,RunningMan情侶成真!戀情細節全梳理!
從瀏覽器多進程到JS單線程,JS運行機制最全面的一次梳理
VCSEL激光器應用及主要廠商梳理|半導體行業觀察