小談java內部類物件的生成過程

weixin_33860722發表於2016-09-09

簡書 佔小狼
轉載請註明原創出處,謝謝!

內部類指在一個外部類的內部再定義一個類,有點廢話...,分為靜態內部類和成員內部類,平常使用較多的為靜態內部類,使用方式和普通類一樣,本文準備在位元組碼層面看看成員內部類物件的生成過程。

public class Outer {  
  public class Inner { }  
  public static void main(String[] args) {  
    Outer outer = new Outer();  
    Outer.Inner inner = outer.new Inner();  
  }  
}  

採用javap -c Outer命令檢視位元組碼指令

2184951-88f6493f71535f50.png

1、第18行的invokespecial指令,呼叫Inner類的構造方法,並傳入outer例項作為引數,所以在inner例項中可以訪問外部類例項;
2、在14行中呼叫了outer.getClass()方法,得到的結果又在17行的pop指令拋棄了,是不是很奇怪?

先看看Java語言規範

15.9.4 Run-time Evaluation of Class Instance Creation Expressions
At run time, evaluation of a class instance creation expression is as follows. First, if the class instance creation expression is a qualified class instance creation expression, the qualifying primary expression is evaluated. If the qualifying expression evaluates to null, a NullPointerException is raised, and the class instance creation expression completes abruptly. If the qualifying expression completes abruptly, the class instance creation expression completes abruptly for the same reason.

該小節規定了在進行例項化操作時,必須對錶達式進行空指標驗證,如果表示式為null,則丟擲NullPointerException,對應上述例子中,必須對outer物件進行驗證。

規範中只是明確了“要丟擲NullPointerException”的行為,至於如何實現null檢查的則沒規定,可以自由實現,比如用普通的if...else做驗證,只不過生成的位元組碼就比呼叫getClass()的辦法更長一些,getClass()方法在Object上宣告的,所有物件上必然存在,由final修飾,保證了有確定的行為,而且執行開銷比較低。

參考
javac在編譯建立內部類物件時生成的奇怪的getClass()呼叫是什麼?


我是佔小狼
座標魔都,白天是上班族,晚上是知識的分享者
如果讀完覺得有收穫的話,歡迎點贊加關注


2184951-aee7d0b635a9e997.jpg
我的微信公眾號

相關文章