這篇文章將為大家詳細(xì)講解有關(guān)如何通過字節(jié)碼看java中this的隱式傳參,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
前言
從字節(jié)碼看java中 this 隱式傳參具體體現(xiàn)(和python中的self如出一轍,但是比python中藏得更深),也發(fā)現(xiàn)了 static 與 非 static 方法的區(qū)別所在!
static與非static方法都是存儲(chǔ)java的方法區(qū)。在static 方法中,沒有this引用,因此無法使用當(dāng)前類中所定義的變量,而非static方法則會(huì)默認(rèn)傳入this。
概述
this關(guān)鍵字,是一個(gè)隱式參數(shù),另外一個(gè)隱式參數(shù)是super。
this用于方法里面,用于方法外面無意義。
this關(guān)鍵字一般用于set方法和構(gòu)造方法中。
我們今天就從另一個(gè)角度來真實(shí)看一下這個(gè)答案吧!
來個(gè)例子,并將其反編譯為可視代碼:
public class Hello { private final int ii; public Hello(int a) { ii = a; } public static void main(String[] args) throws Exception { sayHelloStatic("ok"); } public void sayHello(String word) { System.out.println("hello, " + word); } public static void sayHelloStatic(String word) { System.out.println("static hello, " + word); } }
反匯編命令:
javap -verbose Hello.class
反匯編結(jié)果:
Classfile /D:/xx/target/classes/com/xx/api/Hello.class Last modified 2018-11-8; size 1069 bytes MD5 checksum 9d39cd9d4e95588a73c059a4e69f01e8 Compiled from "Hello.java" public class com.xx.api.Hello minor version: 0 major version: 52 flags: ACC_PUBLIC, ACC_SUPER Constant pool: #1 = Methodref #14.#38 // java/lang/Object."<init>":()V #2 = Fieldref #13.#39 // com/xx/api/Hello.ii:I #3 = String #40 // ok #4 = Methodref #13.#41 // com/xx/api/Hello.sayHelloStatic:(Ljava/lang/String;)V #5 = Fieldref #42.#43 // java/lang/System.out:Ljava/io/PrintStream; #6 = Class #44 // java/lang/StringBuilder #7 = Methodref #6.#38 // java/lang/StringBuilder."<init>":()V #8 = String #45 // hello, #9 = Methodref #6.#46 // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; #10 = Methodref #6.#47 // java/lang/StringBuilder.toString:()Ljava/lang/String; #11 = Methodref #48.#49 // java/io/PrintStream.println:(Ljava/lang/String;)V #12 = String #50 // static hello, #13 = Class #51 // com/xx/api/Hello #14 = Class #52 // java/lang/Object #15 = Utf8 ii #16 = Utf8 I #17 = Utf8 <init> #18 = Utf8 (I)V #19 = Utf8 Code #20 = Utf8 LineNumberTable #21 = Utf8 LocalVariableTable #22 = Utf8 this #23 = Utf8 Lcom/xx/api/Hello; #24 = Utf8 a #25 = Utf8 main #26 = Utf8 ([Ljava/lang/String;)V #27 = Utf8 args #28 = Utf8 [Ljava/lang/String; #29 = Utf8 Exceptions #30 = Class #53 // java/lang/Exception #31 = Utf8 sayHello #32 = Utf8 (Ljava/lang/String;)V #33 = Utf8 word #34 = Utf8 Ljava/lang/String; #35 = Utf8 sayHelloStatic #36 = Utf8 SourceFile #37 = Utf8 Hello.java #38 = NameAndType #17:#54 // "<init>":()V #39 = NameAndType #15:#16 // ii:I #40 = Utf8 ok #41 = NameAndType #35:#32 // sayHelloStatic:(Ljava/lang/String;)V #42 = Class #55 // java/lang/System #43 = NameAndType #56:#57 // out:Ljava/io/PrintStream; #44 = Utf8 java/lang/StringBuilder #45 = Utf8 hello, #46 = NameAndType #58:#59 // append:(Ljava/lang/String;)Ljava/lang/StringBuilder; #47 = NameAndType #60:#61 // toString:()Ljava/lang/String; #48 = Class #62 // java/io/PrintStream #49 = NameAndType #63:#32 // println:(Ljava/lang/String;)V #50 = Utf8 static hello, #51 = Utf8 com/xx/api/Hello #52 = Utf8 java/lang/Object #53 = Utf8 java/lang/Exception #54 = Utf8 ()V #55 = Utf8 java/lang/System #56 = Utf8 out #57 = Utf8 Ljava/io/PrintStream; #58 = Utf8 append #59 = Utf8 (Ljava/lang/String;)Ljava/lang/StringBuilder; #60 = Utf8 toString #61 = Utf8 ()Ljava/lang/String; #62 = Utf8 java/io/PrintStream #63 = Utf8 println { public com.xx.api.Hello(int); descriptor: (I)V flags: ACC_PUBLIC Code: stack=2, locals=2, args_size=2 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: aload_0 5: iload_1 6: putfield #2 // Field ii:I 9: return LineNumberTable: line 14: 0 line 15: 4 line 16: 9 LocalVariableTable: Start Length Slot Name Signature 10 0 this Lcom/xx/api/Hello; 10 1 a I public static void main(java.lang.String[]) throws java.lang.Exception; descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=1, args_size=1 0: ldc #3 // String ok 2: invokestatic #4 // Method sayHelloStatic:(Ljava/lang/String;)V 5: return LineNumberTable: line 42: 0 line 45: 5 LocalVariableTable: Start Length Slot Name Signature 6 0 args [Ljava/lang/String; Exceptions: throws java.lang.Exception public void sayHello(java.lang.String); descriptor: (Ljava/lang/String;)V flags: ACC_PUBLIC Code: stack=3, locals=2, args_size=2 0: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream; 3: new #6 // class java/lang/StringBuilder 6: dup 7: invokespecial #7 // Method java/lang/StringBuilder."<init>":()V 10: ldc #8 // String hello, 12: invokevirtual #9 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 15: aload_1 16: invokevirtual #9 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 19: invokevirtual #10 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 22: invokevirtual #11 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 25: return LineNumberTable: line 48: 0 line 49: 25 LocalVariableTable: Start Length Slot Name Signature 26 0 this Lcom/xx/api/Hello; 26 1 word Ljava/lang/String; public static void sayHelloStatic(java.lang.String); descriptor: (Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=3, locals=1, args_size=1 0: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream; 3: new #6 // class java/lang/StringBuilder 6: dup 7: invokespecial #7 // Method java/lang/StringBuilder."<init>":()V 10: ldc #12 // String static hello, 12: invokevirtual #9 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 15: aload_0 16: invokevirtual #9 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 19: invokevirtual #10 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 22: invokevirtual #11 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 25: return LineNumberTable: line 51: 0 line 52: 25 LocalVariableTable: Start Length Slot Name Signature 26 0 word Ljava/lang/String; } SourceFile: "Hello.java"
我們從字節(jié)碼文件中可以看出來:
sayHello(String word) 和 sayHelloStatic(String word) 都只有一個(gè)參數(shù),但是在字節(jié)碼中:
sayHello(String word) 中引用 word 時(shí)使用了 15: aload_1, 可以看出其加載的變量是在 slot1中,而 slot0中即保存了 this 。
sayHelloStatic(String word) 中引用 word 時(shí)使用了 15: aload_0, 可以看出靜態(tài)方法中,直接將變量存在了 slot0中,因此無法使用 this 中的變量了。
當(dāng)要操作當(dāng)前類的變量或方法時(shí),需要先 aload_0, 然后再做相關(guān)操作!
關(guān)于“如何通過字節(jié)碼看java中this的隱式傳參”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。
文章標(biāo)題:如何通過字節(jié)碼看java中this的隱式傳參-創(chuàng)新互聯(lián)
網(wǎng)站URL:http://www.rwnh.cn/article22/johjc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站導(dǎo)航、網(wǎng)站內(nèi)鏈、品牌網(wǎng)站設(shè)計(jì)、域名注冊(cè)、網(wǎng)站收錄、軟件開發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容