<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
這是一個 Java 內部類的簡單實現:
public class OutterJava { private void printOut() { System.out.println("AAA"); } class InnJava { public void printInn() { printOut(); } } }
外部類是一個私有方法,內部類為什麼可以存取到外部類的私有方法呢?思考這個問題,首先要從它的位元組碼入手,看看 JVM 到底對 java 檔案做了什麼。
位元組碼分析流程是:
javac xxx.java
生成 class 檔案。javap -c xxx.class
對程式碼進行反組合,可以生成可檢視的程式碼內容。通過 javac 命令生成 class 檔案,此時會發現生成了兩個 class 檔案,一個外部類 OtterJava 的,一個內部類 InnJava 的。
OutterJava.class 反組合後的程式碼如下所示,這裡面除了一個構造方法,多生成了一個
Compiled from "OutterJava.java" public class java.OutterJava { public java.OutterJava(); Code: 0: aload_0 1: invokespecial #2 // Method java/lang/Object."<init>":()V 4: return private void printOut(); Code: 0: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #4 // String AAA 5: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: return static void access$000(java.OutterJava); Code: 0: aload_0 1: invokespecial #1 // Method printOut:()V 4: return }
從反編譯出來的內容來看,多了一個靜態的access$000(OutterJava)
方法,它的內部呼叫了 printOut()
。
Compiled from "OutterJava.java" class java.OutterJava$InnJava { final java.OutterJava this$0; java.OutterJava$InnJava(java.OutterJava); Code: 0: aload_0 1: aload_1 2: putfield #1 // Field this$0:Ljava/OutterJava; 5: aload_0 6: invokespecial #2 // Method java/lang/Object."<init>":()V 9: return public void printInn2(); Code: 0: aload_0 1: getfield #1 // Field this$0:Ljava/OutterJava; 4: invokestatic #3 // Method java/OutterJava.access$000:(Ljava/OutterJava;)V 7: return }
在 InnJava 的位元組碼反編譯出來的內容中,主要有兩個點需要注意:
this$0
中。OutterJava.access$000
方法。小結:
在 Java 中,內部類與外部類的關係是:
this$0
中。access$000
,內部類可以通過這個靜態方法存取到外部類中的私有方法。同樣的 Java 程式碼,用 Kotlin 實現:
class Outter { private fun printOut() { println("Out") } inner class Inner { fun printIn() { printOut() } } }
這裡如果不加inner
關鍵字,printIn()
內的printOut()
會報錯Unresolved reference: printOut
。
不加inner
關鍵字,反編譯後的位元組碼:
public final class java/Outter$Inner { // ... public <init>()V L0 LINENUMBER 8 L0 ALOAD 0 INVOKESPECIAL java/lang/Object.<init> ()V RETURN L1 LOCALVARIABLE this Ljava/Outter$Inner; L0 L1 0 MAXSTACK = 1 MAXLOCALS = 1 // ... }
不加inner
關鍵字,內部類的構造方法是沒有外部類範例引數的。如果加上inner
,就和 Java 一樣:
// 加上了 inner 的構造方法 public <init>(Ljava/Outter;)V L0 LINENUMBER 8 L0 ALOAD 0 ALOAD 1 PUTFIELD java/Outter$Inner.this$0 : Ljava/Outter; ALOAD 0 INVOKESPECIAL java/lang/Object.<init> ()V RETURN L1 LOCALVARIABLE this Ljava/Outter$Inner; L0 L1 0 LOCALVARIABLE this$0 Ljava/Outter; L0 L1 1 MAXSTACK = 2 MAXLOCALS = 2
而內部類對於外部類私有方法的存取,也是通過靜態方法access$XXX
來實現的:
public final static synthetic access$printOut(Ljava/Outter;)V L0 LINENUMBER 3 L0 ALOAD 0 INVOKESPECIAL java/Outter.printOut ()V RETURN L1 LOCALVARIABLE $this Ljava/Outter; L0 L1 0 MAXSTACK = 1 MAXLOCALS = 1
在 Kotlin 中,內部類持有外部類參照和通過靜態方法存取外部類私有方法都是與 Java 一樣的。唯一的不同是,Kotlin 中需要使用 inner
關鍵字修飾內部類,才能存取外部類中的內容。實質是inner
關鍵字會控制內部類的構造方法是否帶有外部類範例引數。
到此這篇關於Java中的Kotlin 內部類原理的文章就介紹到這了,更多相關Java Kotlin 內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45