/**
* @author wangcheng
* @date 17/12/20
*/
public class Outer {
/*
Outer外部類的反編譯結(jié)果,可以發(fā)現(xiàn)對(duì)于私有變量data的訪問(wèn)實(shí)際上是通過(guò)access$000()方法進(jìn)行的
public class com.thinkjoy.InnerClass.Outer {
public com.thinkjoy.InnerClass.Outer();
public void local(java.lang.String, java.lang.String);
public static void main(java.lang.String[]);
static int access$000(com.thinkjoy.InnerClass.Outer);
}
static int access$100(com.thinkjoy.InnerClass.Outer);
Code:
0: aload_0
1: getfield #1 // Field data:I
4: ireturn
aload_0: 對(duì)static方法來(lái)說(shuō)獲取第一個(gè)參數(shù),對(duì)非static方法來(lái)說(shuō)是this
getfield: 獲取Outer的data字段
ireturn: 返回int類型
*/
// 為什么內(nèi)部類可以訪問(wèn)外部類的私有變量?
// 首先,在編譯后,該內(nèi)部類和外部類是兩個(gè)獨(dú)立的文件Outer.class和Outer$MemberInner.class
// 那么,兩個(gè)獨(dú)立類怎么可以訪問(wèn)到自己的成員變量,
// 一種方式是直接在類內(nèi)部--這種顯然是不對(duì)的,因?yàn)橐呀?jīng)編譯成兩個(gè)類文件了
// 第二種方式是通過(guò)該類的對(duì)象訪問(wèn),但是對(duì)象只能訪問(wèn)可見(jiàn)的成員變量,如protected修飾的變量,只能在同包和子類中通過(guò)對(duì)象直接訪問(wèn),
// 那么怎么訪問(wèn)private呢?
// 通過(guò)查看反編譯文件,得知Outer.class中多出了access$000(Outer)這么一個(gè)靜態(tài)方法,這個(gè)方法返回值就是data
// 如步驟③,內(nèi)部類直接可以訪問(wèn)外部類的data,實(shí)際執(zhí)行的語(yǔ)句是這樣的 System.out.println(Outer.access$000(this$0));
//
// 對(duì)于access$000方法不考慮傳入的外部類實(shí)例是否可以在其他類中獲取該實(shí)例的私有成員變量
// 訪問(wèn)修飾符是代碼層面的可見(jiàn)性控制,而access$000是編譯器直接生成的字節(jié)碼,故可以訪問(wèn)
private int data = 0;
static String str = "www";
//成員內(nèi)部類,訪問(wèn)修飾符可以是private,protected,default,public
class MemberInner {
//static int i = 0; 不能有static局部變量,因?yàn)槌蓡T內(nèi)部類要在外部類實(shí)例創(chuàng)建之后才能創(chuàng)建,當(dāng)內(nèi)部類為講臺(tái)局部?jī)?nèi)部類的時(shí)候是可以的
private int count = 0;
/*
class com.thinkjoy.InnerClass.Outer$MemberInner {
final com.thinkjoy.InnerClass.Outer this$0;
com.thinkjoy.InnerClass.Outer$MemberInner(com.thinkjoy.InnerClass.Outer);
void print();
static int access$000(com.thinkjoy.InnerClass.Outer$MemberInner);
Code:
0: aload_0
1: getfield #1 // Field count:I
4: ireturn
}
*/
/*
Outer.MemberInner memberInner = new Outer().new MemberInner() {
//nothing to do
};
memberInner.print();
當(dāng)在其他類中進(jìn)行執(zhí)行上述代碼,不會(huì)輸出任何東西,
*/
void print() {
//③可以訪問(wèn)外部類的私有變量
System.out.println(data);
System.out.println(str);
}
class InnerMemberInner{
/*
class com.thinkjoy.InnerClass.Outer$MemberInner$InnerMemberInner {
final com.thinkjoy.InnerClass.Outer$MemberInner this$1;
com.thinkjoy.InnerClass.Outer$MemberInner$InnerMemberInner(com.thinkjoy.InnerClass.Outer$MemberInner);
void innerPrint();
Code:
0: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
3: aload_0
4: getfield #1 // Field this$1:Lcom/thinkjoy/InnerClass/Outer$MemberInner;
7: invokestatic #4 // Method com/thinkjoy/InnerClass/Outer$MemberInner.access$000:(Lcom/thinkjoy/InnerClass/Outer$MemberInner;)I
10: invokevirtual #5 // Method java/io/PrintStream.println:(I)V
13: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
16: aload_0
17: getfield #1 // Field this$1:Lcom/thinkjoy/InnerClass/Outer$MemberInner;
20: getfield #6 // Field com/thinkjoy/InnerClass/Outer$MemberInner.this$0:Lcom/thinkjoy/InnerClass/Outer;
23: invokestatic #7 // Method com/thinkjoy/InnerClass/Outer.access$100:(Lcom/thinkjoy/InnerClass/Outer;)I
26: invokevirtual #5 // Method java/io/PrintStream.println:(I)V
29: return
}
*/
void innerPrint(){
System.out.println(count);
System.out.println(data);
}
}
}
//局部?jī)?nèi)部類,不允許有修飾符,類似局部變量
public void local(final String name, String age) {
//①定義在代碼塊中,只能在代碼塊中訪問(wèn)
//{
// class LocalInner1 {
//
// }
//}
//②編譯報(bào)錯(cuò),找不到該類的符號(hào)
//new LocalInner(){
//
//};
//定義在方法中,可以在方法中訪問(wèn),且實(shí)例化的代碼必須在定義之后,否則無(wú)法訪問(wèn),同②
class LocalInner {
/*
該局部?jī)?nèi)部類的
class com.thinkjoy.InnerClass.Outer$1LocalInner {
final java.lang.String val$name;
final com.thinkjoy.InnerClass.Outer this$0;
com.thinkjoy.InnerClass.Outer$1(com.thinkjoy.InnerClass.Outer, java.lang.String);
public void print();
}
*/
public void print() {
// name是外部類local方法的參數(shù),且name必須為final,
// 為什么需要是final?
// 可以發(fā)現(xiàn),上面的注釋是該局部?jī)?nèi)部類的反編譯代碼,
// 發(fā)現(xiàn)編譯器將該類重新生成一個(gè)單獨(dú)的Outer$1LocalInner類,與Outer同包,
// 在該類中,編譯器新增了一個(gè)final的成員變量val$name,也就是Outer的local參數(shù)name的備份,
// 假如local的name不是final的,也就是name是可以更改的,那么是不是局部?jī)?nèi)部類中的val$name也需要做修改
// 所以,編譯器規(guī)定,local的name是final的,不可修改,val$name也就是final(因?yàn)閚ame不會(huì)變了)
System.out.println(name);
}
}
//匿名內(nèi)部類,沒(méi)有名字的內(nèi)部類,其實(shí)是繼承Outer$1LocalInner類,編譯器生成的默認(rèn)名字是Outer$1
LocalInner localInner = new LocalInner() {
/*
該匿名內(nèi)部類的
class com.thinkjoy.InnerClass.Outer$1 extends com.thinkjoy.InnerClass.Outer$1LocalInner {
final java.lang.String val$name;
final com.thinkjoy.InnerClass.Outer this$0;
//包可見(jiàn)的構(gòu)造方法,可以設(shè)置外部類的引用this$0與外部類local方法參數(shù)name的備份
com.thinkjoy.InnerClass.Outer$1(com.thinkjoy.InnerClass.Outer, java.lang.String);
public void print();
}
*/
@Override
public void print() {
//name是外部類local方法的參數(shù),且name必須為final
System.out.println(name);
System.out.println(data);
}
};
localInner.print();
}
//嵌套內(nèi)部類--staic修飾的內(nèi)部類
static class StaticInner {
//可以有靜態(tài)的成員變量,并且可以有修飾符
private static int data = 0;
}
public static void main(String[] args) {
// ①成員內(nèi)部類的修飾符為private,在當(dāng)前類中是可以訪問(wèn)內(nèi)部類的,但是在其他類中是不能訪問(wèn)內(nèi)部類的
// 同理,其他訪問(wèn)修飾符是跟成員變量的修飾符的作用是一樣的
MemberInner memberInner = new Outer().new MemberInner();
//②嵌套內(nèi)部類
// System.out.println(StaticInner.data);//可以直接訪問(wèn),并且可以根據(jù)修飾符調(diào)整可見(jiàn)性
}
}
java內(nèi)部類
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
相關(guān)閱讀更多精彩內(nèi)容
- 1)首先,用內(nèi)部類是因?yàn)閮?nèi)部類與所在外部類有一定的關(guān)系,往往只有該外部類調(diào)用此內(nèi)部類。所以沒(méi)有必要專門(mén)用一個(gè)Jav...
- 1.成員內(nèi)部類 可以把一個(gè)內(nèi)部類看做一個(gè)成員。成員內(nèi)部類可以無(wú)條件訪問(wèn)外部類的所有成員屬性和成員方法。 當(dāng)成員內(nèi)部...
- 匿名內(nèi)部類 ;顧名思義,匿名內(nèi)部類是沒(méi)有名字的類,并且適用于只想創(chuàng)建一個(gè) 子類對(duì)象優(yōu)點(diǎn):書(shū)寫(xiě)格式簡(jiǎn)單弊端:只能用...
- 局部?jī)?nèi)部類是定義在函數(shù)的內(nèi)部,不可以用訪問(wèn)修飾符修飾,只能在函數(shù)內(nèi)部使用,隨著函數(shù)的調(diào)用而使用,只能在該函數(shù)中實(shí)例...