欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

通過(guò)字節(jié)碼看java中this的隱式傳參詳解

 更新時(shí)間:2018年11月09日 08:38:00   作者:等你歸去來(lái)  
這篇文章主要給大家介紹了關(guān)于如何通過(guò)字節(jié)碼看java中this的隱式傳參的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

前言

從字節(jié)碼看java中 this 隱式傳參具體體現(xiàn)(和python中的self如出一轍,但是比python中藏得更深),也發(fā)現(xiàn)了 static 與 非 static 方法的區(qū)別所在!

static與非static方法都是存儲(chǔ)java的方法區(qū)。在static 方法中,沒(méi)有this引用,因此無(wú)法使用當(dāng)前類(lèi)中所定義的變量,而非static方法則會(huì)默認(rèn)傳入this。

概述

  • this關(guān)鍵字,是一個(gè)隱式參數(shù),另外一個(gè)隱式參數(shù)是super。
  • this用于方法里面,用于方法外面無(wú)意義。
  • this關(guān)鍵字一般用于set方法和構(gòu)造方法中。

我們今天就從另一個(gè)角度來(lái)真實(shí)看一下這個(gè)答案吧!

來(lái)個(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é)碼文件中可以看出來(lái):

  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中,因此無(wú)法使用 this 中的變量了。

當(dāng)要操作當(dāng)前類(lèi)的變量或方法時(shí),需要先 aload_0, 然后再做相關(guān)操作!

總結(jié):

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • SpringCloud整合Activiti過(guò)程中的踩坑記錄

    SpringCloud整合Activiti過(guò)程中的踩坑記錄

    由于項(xiàng)目需要,最近開(kāi)始在項(xiàng)目Spring boot中集成工作流引擎Activiti,由于第一次集成,一路上步步都是坑,所以這篇文章主要給大家介紹了關(guān)于SpringCloud整合Activiti過(guò)程中所遇到的踩坑記錄,需要的朋友可以參考下
    2021-09-09
  • SpringBoot如何手寫(xiě)一個(gè)starter并使用這個(gè)starter詳解

    SpringBoot如何手寫(xiě)一個(gè)starter并使用這個(gè)starter詳解

    starter是SpringBoot中的一個(gè)新發(fā)明,它有效的降低了項(xiàng)目開(kāi)發(fā)過(guò)程的復(fù)雜程度,對(duì)于簡(jiǎn)化開(kāi)發(fā)操作有著非常好的效果,下面這篇文章主要給大家介紹了關(guān)于SpringBoot如何手寫(xiě)一個(gè)starter并使用這個(gè)starter的相關(guān)資料,需要的朋友可以參考下
    2022-12-12
  • 如何利用Spring?MVC實(shí)現(xiàn)RESTful風(fēng)格

    如何利用Spring?MVC實(shí)現(xiàn)RESTful風(fēng)格

    這篇文章主要介紹了如何利用Spring?MVC實(shí)現(xiàn)RESTful風(fēng)格,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • Java實(shí)現(xiàn)excel大數(shù)據(jù)量導(dǎo)入

    Java實(shí)現(xiàn)excel大數(shù)據(jù)量導(dǎo)入

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)excel大數(shù)據(jù)量導(dǎo)入,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-08-08
  • JAVA如何按字節(jié)截取字符串

    JAVA如何按字節(jié)截取字符串

    這篇文章主要介紹了JAVA如何按字節(jié)截取字符串,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-01-01
  • springboot項(xiàng)目打包發(fā)布部署的過(guò)程及jar和war的區(qū)別

    springboot項(xiàng)目打包發(fā)布部署的過(guò)程及jar和war的區(qū)別

    Spring Boot使用了內(nèi)嵌容器,因此它的部署方式也變得非常簡(jiǎn)單靈活,可以將Spring Boot項(xiàng)目打包成JAR包來(lái)獨(dú)立運(yùn)行,Spring Boot項(xiàng)目既可以生成WAR包發(fā)布,也可以生成JAR包發(fā)布,那么它們有什么區(qū)別呢
    2022-11-11
  • 詳解Java七大阻塞隊(duì)列之SynchronousQueue

    詳解Java七大阻塞隊(duì)列之SynchronousQueue

    SynchronousQueue不需要存儲(chǔ)線程間交換的數(shù)據(jù),它的作用像是一個(gè)匹配器,使生產(chǎn)者和消費(fèi)者一一匹配。本文詳細(xì)講解了Java七大阻塞隊(duì)列之一SynchronousQueue,需要了解的小伙伴可以參考一下這篇文章
    2021-09-09
  • Java實(shí)現(xiàn)貪吃蛇游戲源碼

    Java實(shí)現(xiàn)貪吃蛇游戲源碼

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)貪吃蛇游戲源碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-11-11
  • Java基礎(chǔ)之代碼死循環(huán)詳解

    Java基礎(chǔ)之代碼死循環(huán)詳解

    這篇文章主要介紹了Java基礎(chǔ)之代碼死循環(huán)詳解,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java基礎(chǔ)的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-04-04
  • MyBatis3源碼解析之如何獲取數(shù)據(jù)源詳解

    MyBatis3源碼解析之如何獲取數(shù)據(jù)源詳解

    用myBatis3與spring整合的時(shí)候,我們可以通過(guò)多種方式獲取數(shù)據(jù)源,下面這篇文章主要給大家介紹了關(guān)于MyBatis3源碼解析之如何獲取數(shù)據(jù)源的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06

最新評(píng)論