Java內(nèi)部類知識匯總
Java內(nèi)部類
一、 含義
在Java編程語言里,程序是由類(class)構(gòu)建而成的。在一個(gè)類的內(nèi)部也可以聲明類,我們把這樣的類叫做內(nèi)部類。
二、 作用
•實(shí)現(xiàn)了更好的封裝,我們知道,普通類(非內(nèi)部類)的訪問修飾符不能為private或protected,而內(nèi)部類可以。當(dāng)我們將內(nèi)部類聲明為private時(shí),只有外部類可以訪問內(nèi)部類,很好地隱藏了內(nèi)部類。
•內(nèi)部類可以繼承(extends)或?qū)崿F(xiàn)(implements)其他的類或接口,而不受外部類的影響。
•內(nèi)部類可以直接訪問外部類的字段和方法,即使是用private修飾的,相反的,外部類不能直接訪問內(nèi)部類的成員。
三、 原理
內(nèi)部類是一個(gè)編譯時(shí)的概念,編譯后會生成兩個(gè)獨(dú)立的class文件,如下:
public class Outer{ private String outerName = "outer"; class Inner{ private String innerName = "inner"; } }
編譯后的文件如下圖:
編譯后Outer.Inner被重命名為Outer$Inner,句點(diǎn)(.)被替換成了美元符號($)。
四、 分類
Java內(nèi)部類可分為成員內(nèi)部類、局部內(nèi)部類、匿名內(nèi)部類、靜態(tài)內(nèi)部類。
1) 成員內(nèi)部類
成員內(nèi)部類可以看成是外部類的一個(gè)成員,在成員內(nèi)部類中無法聲明靜態(tài)成員,但static final字段是個(gè)例外。我們知道加載類時(shí),會先初始化靜態(tài)成員,如果成員內(nèi)部類有靜態(tài)成員,那么內(nèi)部類就會在外部類之前生成,而內(nèi)部類是為外部類服務(wù)的,內(nèi)部類在外部類之前就生成可能會脫離掌控。在實(shí)例化成員內(nèi)部類時(shí),成員內(nèi)部類會持有一個(gè)外部類當(dāng)前對象的引用,這樣在成員內(nèi)部類中就可以直接訪問外部類的成員,即使是private修飾的。
import static java.lang.System.out; public class Outer{ private String outerName = "outer"; //外部類無法直接訪問內(nèi)部類的成員,需要實(shí)例化內(nèi)部類對象 private Inner inner = new Inner(); public class Inner{ private String innerName = "inner"; public void show(){ out.println(outerName); //可以直接訪問外部類的成員 } } public void show(){ out.println(inner.innerName); inner.show(); } public static void main(String[] args){ Outer outer = new Outer(); outer.show(); //實(shí)例化內(nèi)部類 Outer.Inner inner = outer.new Inner(); inner.show(); } }
運(yùn)行結(jié)果:
inner
outer
outer
成員內(nèi)部類對外部類對象的引用,是通過在this前面加上外部類的名字構(gòu)成的,這種形式叫作
限定-this,out.println(outerName)與out.println(Outer.this.outerName)是等價(jià)的。
2) 局部內(nèi)部類
局部內(nèi)部類的使用和成員內(nèi)部類的使用基本一致,只是局部內(nèi)部類定義在外部類的方法中,就像局部變量一樣,并不是外部類的成員。局部內(nèi)部類在方法外是無法訪問到的,但它的實(shí)例可以從方法中返回,并且實(shí)例在不再被引用之前會一直存在。局部內(nèi)部類也可以訪問所在方法的局部變量、方法參數(shù)等,限制是局部變量或方法參數(shù)只有在聲明為final時(shí)才能被訪問?! ?/p>
import static java.lang.System.out; public class Outer{ private String outerName = "outer"; public void show(final String str){ //方法參數(shù)為final類型 class Inner{ public void print(){ out.println(outerName+str); } } Inner inner = new Inner(); inner.print(); } public static void main(String[] args){ Outer outer = new Outer(); outer.show(":lalala"); } }
運(yùn)行結(jié)果:
outer:lalala
3) 匿名內(nèi)部類
可以把匿名內(nèi)部類想象成是沒有類名的局部內(nèi)部類,匿名內(nèi)部類有以下特點(diǎn):
1、匿名內(nèi)部類不能有構(gòu)造器,匿名內(nèi)部類沒有類名,肯定無法聲明構(gòu)造器。
2、匿名內(nèi)部類必須繼承或?qū)崿F(xiàn)一個(gè)接口,指定給new的類型為匿名類的超類型,匿名類不能有顯示的extends或implements子句,也不能有任何修飾符。
3、匿名內(nèi)部類和成員內(nèi)部類、局部內(nèi)部類一樣,也不能聲明靜態(tài)成員?! ?/p>
import static java.lang.System.out; public class Outer{ private String outerName = "outer"; public void show(final String str){ new Inner(){ //實(shí)現(xiàn)了Inner接口 public void print(){ out.println(outerName+str); } }.print(); } public static void main(String[] args){ Outer outer = new Outer(); outer.show(":lalala"); } } interface Inner{ void print(); }
運(yùn)行結(jié)果:
outer:lalala
4) 靜態(tài)內(nèi)部類
靜態(tài)內(nèi)部類,有的書上也稱為嵌套類,聲明它時(shí)需要用static修飾符,靜態(tài)內(nèi)部類不同于前三種內(nèi)部類,靜態(tài)內(nèi)部類不會持有外部類當(dāng)前對象的引用,所以在靜態(tài)內(nèi)部類中無法訪問外部類的非靜態(tài)成員,可以這么說,靜態(tài)內(nèi)部類不依賴于外部類?!?/p>
import static java.lang.System.out; public class Outer{ private String outerName = "outer"; private static int id = 123; private Inner inner = new Inner(); public static class Inner{ public void print1(){ //out.println(outerName); 無法訪問外部類的非靜態(tài)成員 out.println(id); } public static void print2(){ out.println(id); } } public void show(){ inner.print1(); } public static void main(String[] args){ Outer outer = new Outer(); outer.show(); Outer.Inner.print2(); //直接通過類名訪問靜態(tài)內(nèi)部類 } }
相關(guān)文章
SpringBoot啟動時(shí)執(zhí)行初始化操作的幾種方式
項(xiàng)目中,經(jīng)常需要在啟動過程中初始化一些數(shù)據(jù),如從數(shù)據(jù)庫讀取一些配置初始化,或從數(shù)據(jù)庫讀取一些熱點(diǎn)數(shù)據(jù)到redis進(jìn)行初始化緩存,本文給大家介紹了SpringBoot啟動時(shí)執(zhí)行初始化操作的幾種方式的相關(guān)資料,需要的朋友可以參考下2024-05-05Spring?Boot?使用?Disruptor?做內(nèi)部高性能消息隊(duì)列
這篇文章主要介紹了Spring?Boot?使用?Disruptor?做內(nèi)部高性能消息隊(duì)列,工作中遇到項(xiàng)目使用Disruptor做消息隊(duì)列,對你沒看錯(cuò),不是Kafka,也不是rabbitmq。Disruptor有個(gè)最大的優(yōu)點(diǎn)就是快,還有一點(diǎn)它是開源的哦,下面做個(gè)簡單的記錄2022-06-06Java?嵌入數(shù)據(jù)引擎從?SQLite?到?SPL詳解
這篇文章主要介紹了Java?嵌入數(shù)據(jù)引擎:從?SQLite?到?SPL,SQLite架構(gòu)簡單,其核心雖然是C語言開發(fā)的,但封裝得比較好,對外呈現(xiàn)為一個(gè)小巧的Jar包,能方便地集成在Java應(yīng)用中,本文給大家介紹的非常詳細(xì),需要的朋友參考下2022-07-07淺談java反射和自定義注解的綜合應(yīng)用實(shí)例
本篇文章主要介紹了java反射和自定義注解的綜合應(yīng)用,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-09-09