最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java將Lambda表達式對應的類保存到class文件中的方法示例

 更新時間:2026年05月19日 08:32:07   作者:金銀銅鐵  
大家在日常開發(fā)中應該都用過 Lambda表達式,以下面的 java代碼為例,我們在運行 HelloWorld中的 main方法時,可以看到 r的類型信息,但是在編譯時、運行時都沒有看到 r對應的類的 class文件,本文給大家介紹了Java將Lambda表達式對應的類保存到class文件中的方法示例

背景

大家在日常開發(fā)中應該都用過 Lambda表達式。以下面的 java代碼為例,我們在運行 HelloWorld中的 main方法時,可以看到 r的類型信息,但是在編譯時、運行時都沒有看到 r對應的類的 class文件,有沒有辦法將 r對應的類保存到 class文件里呢?本文會對此進行探討。

public class HelloWorld {
    public static void main(String[] args) {
        Runnable r = () -> System.out.println("Hello World");
        r.run();
        System.out.println("class name of r: " + r.getClass().getName());	
    }
}

要點

運行 java命令時,使用以下兩個選項中的任何一個,都可以把 Lambda表達式對應的類自動保存到 class 文件中

  • -Djdk.invoke.LambdaMetafactory.dumpProxyClassFiles
  • -Djdk.invoke.LambdaMetafactory.dumpProxyClassFiles=true

正文

javac版本和java版本

查看javac版本

使用如下命令可以查看 javac命令的版本

javac -version

該命令在我電腦上的運行結果如下

javac 21

查看java版本

使用如下命令可以查看 java命令的版本

java -version

該命令在我電腦上的運行結果如下

openjdk version "21" 2023-09-19
OpenJDK Runtime Environment (build 21+35-2513)
OpenJDK 64-Bit Server VM (build 21+35-2513, mixed mode, sharing)

代碼

請將如下代碼保存為 HelloWorld.java ??

public class HelloWorld {
    public static void main(String[] args) {
        Runnable r = () -> System.out.println("Hello World");
        r.run();
        System.out.println("class name of r: " + r.getClass().getName());	
    }
}

編譯

使用如下的命令可以編譯 HelloWorld.java\

javac -parameters HelloWorld.java

編譯之后,執(zhí)行 tree . 命令,會看到這樣的結果 ?? (當前目錄多了 HelloWorld.class 文件)

.
├── HelloWorld.class
└── HelloWorld.java

1 directory, 2 files

運行

使用如下的命令可以編譯 HelloWorld中的 main方法 ??

java HelloWorld

在我電腦上,該命令的運行結果如下 ?? (在您的電腦上,最后一行輸出的類名可能是其他內容)

Hello World
class name of r: HelloWorld$$Lambda/0x000000d001000a00

看來 r的精確類型(為了便于描述,我們把它簡稱為 L吧)是一個很特殊的類(至少命名很特殊??)。在運行完 HelloWorld中的 main方法之后,當前目錄并沒有新的文件生成。如果我們想看看 L的內容,一個思路是讓 java虛擬機把 L保存到 class文件里(我們可以用 javap命令來查看 class文件的內容)。

在 InnerClassLambdaMetafactory.java 里可以找到如下的選項 ??

看起來只要加上以下兩個選項的任何一個,就可以將 r對應的類保存到 class文件里

  • -Djdk.invoke.LambdaMetafactory.dumpProxyClassFiles
  • -Djdk.invoke.LambdaMetafactory.dumpProxyClassFiles=true

我們就用第一種方法吧,完整的命令如下 ??

java -Djdk.invoke.LambdaMetafactory.dumpProxyClassFiles HelloWorld

運行完這個命令后,再運行 tree . 命令,會得到以下結果 ?? (在您的電腦上,所看到的 class\text{class}class 文件的名稱可能會有差異)

.
├── DUMP_LAMBDA_PROXY_CLASS_FILES
│   └── HelloWorld$$Lambda.0x000000f801000a00.class
├── HelloWorld.class
└── HelloWorld.java
2 directories, 3 files

當前目錄多了一個名為 DUMP_LAMBDA_PROXY_CLASS_FILES 的目錄,這個目錄下有一個 class文件。我們用如下的命令可以查看這個 class文件的內容

javap -v -p DUMP_LAMBDA_PROXY_CLASS_FILES/*class

我電腦上的運行結果如下 ?? (這里略去了結果中的前三行)

final class HelloWorld$$Lambda implements java.lang.Runnable
  minor version: 0
  major version: 65
  flags: (0x1030) ACC_FINAL, ACC_SUPER, ACC_SYNTHETIC
  this_class: #2                          // HelloWorld$$Lambda
  super_class: #4                         // java/lang/Object
  interfaces: 1, fields: 0, methods: 2, attributes: 0
Constant pool:
   #1 = Utf8               HelloWorld$$Lambda
   #2 = Class              #1             // HelloWorld$$Lambda
   #3 = Utf8               java/lang/Object
   #4 = Class              #3             // java/lang/Object
   #5 = Utf8               java/lang/Runnable
   #6 = Class              #5             // java/lang/Runnable
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = NameAndType        #7:#8          // "<init>":()V
  #10 = Methodref          #4.#9          // java/lang/Object."<init>":()V
  #11 = Utf8               run
  #12 = Utf8               HelloWorld
  #13 = Class              #12            // HelloWorld
  #14 = Utf8               lambda$main$0
  #15 = NameAndType        #14:#8         // lambda$main$0:()V
  #16 = Methodref          #13.#15        // HelloWorld.lambda$main$0:()V
  #17 = Utf8               Code
{
  private HelloWorld$$Lambda();
    descriptor: ()V
    flags: (0x0002) ACC_PRIVATE
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #10                 // Method java/lang/Object."<init>":()V
         4: return

  public void run();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=0, locals=1, args_size=1
         0: invokestatic  #16                 // Method HelloWorld.lambda$main$0:()V
         3: return
}

由于它的內容并不多,我們可以嘗試手動反編譯它,反編譯的結果如下 ??

// 以下內容是我手動反編譯的結果,不保證完全準確,僅供參考

final class HelloWorld$$Lambda implements java.lang.Runnable {
  private HelloWorld$$Lambda() {
    super();
  }

  public void run() {
      HelloWorld.lambda$main$0();
  }
}

可以看到 run() 方法里會調用 HelloWorld 中的靜態(tài)方法 lambda$main$0。但是我們在 Hello.java中并沒有定義這樣的靜態(tài)方法,那我們順便把 HelloWorld.class的內容也看一下吧 ?? (使用如下的命令就可以查看 HelloWorld.class文件的詳細內容)

javap -v -p HelloWorld

完整的結果有點長,這里就不展示了。我手動對 HelloWorld.class\text{HelloWorld.class}HelloWorld.class 的內容進行了反編譯,結果如下 ??

// 以下內容是我手動反編譯的結果,不保證完全準確,僅供參考

public class HelloWorld {
  public HelloWorld() {
    super();
  }
  
  public static void main(String[] arg) {
    // 這里涉及一些特殊字節(jié)碼指令,有點復雜,所以略去具體的內容
  }
  
  // 這是一個合成方法,原始的 java 代碼中沒有它
  private static void lambda$main$0() {
    System.out.println("Hello World");
  }
}

簡要的類圖如下 ??

其他

繪制“簡要的類圖”所用到的代碼

我用了 IntelliJ IDEA 中的 PlantUML 插件來畫那張圖,完整的代碼如下 ??

@startuml
'https://plantuml.com/component-diagram

title 簡要的類圖
caption \n\n
' caption 的內容是為了防止掘金平臺生成的水印遮蓋圖中的文字

class HelloWorld {
  + HelloWorld()
  + {static} void main(String[] arg)
  - {static} void lambda$main$0()
}

interface java.lang.Runnable
class HelloWorld$$Lambda
java.lang.Runnable <|.. HelloWorld$$Lambda

interface java.lang.Runnable {
    void run()
}

class HelloWorld$$Lambda {
  - HelloWorld$$Lambda()
  + void run()
}

note left of HelloWorld$$Lambda::run
<code>
public void run() {
  HelloWorld.lambda$main$0();
}
</code>
end note

note left of HelloWorld::lambda$main$0
這是一個合成方法,
可以認為它的代碼是這樣的 <:point_down:>
<code>
private static void lambda$main$0() {
  System.out.println("Hello World");
}
</code>
end note

@enduml

以上就是Java將Lambda表達式對應的類保存到class文件中的方法示例的詳細內容,更多關于Java將Lambda對應類保存到class的資料請關注腳本之家其它相關文章!

相關文章

  • springboot整合couchbase集群的步驟

    springboot整合couchbase集群的步驟

    couchbase是一款開源的,分布式的nosql數(shù)據庫,主要用于分布式緩存和數(shù)據存儲領域,本文給大家介紹springboot整合couchbase集群的步驟,感興趣的朋友一起看看吧
    2025-03-03
  • 徹底搞懂Java多線程(四)

    徹底搞懂Java多線程(四)

    這篇文章主要給大家介紹了關于Java面試題之多線程和高并發(fā)的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用java具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2021-07-07
  • 淺談springBoot注解大全

    淺談springBoot注解大全

    本篇文章主要介紹了淺談springBoot注解大全,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-03-03
  • 淺談一下Java中集合的迭代方式

    淺談一下Java中集合的迭代方式

    這篇文章主要介紹了淺談一下Java中集合的迭代方式,可以幫助我們學習,理解函數(shù)式編程,需要的朋友可以參考下
    2023-04-04
  • JVM進程緩存Caffeine的使用

    JVM進程緩存Caffeine的使用

    本文主要介紹了JVM進程緩存Caffeine的使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-01-01
  • Java動態(tài)獲取實現(xiàn)某個接口下所有的實現(xiàn)類對象集合

    Java動態(tài)獲取實現(xiàn)某個接口下所有的實現(xiàn)類對象集合

    今天小編就為大家分享一篇關于Java動態(tài)獲取實現(xiàn)某個接口下所有的實現(xiàn)類對象集合,小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • SpringBoot整合SQLite數(shù)據庫全過程

    SpringBoot整合SQLite數(shù)據庫全過程

    sqlite是一個很輕量級的數(shù)據庫,可以滿足日常sql的需求,下面這篇文章主要給大家介紹了關于SpringBoot整合SQLite數(shù)據庫的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-03-03
  • Java調用Python代碼實現(xiàn)Word轉化為PDF格式

    Java調用Python代碼實現(xiàn)Word轉化為PDF格式

    這篇文章主要為大家詳細介紹了Java如何實現(xiàn)調用Python代碼實現(xiàn)Word轉化為PDF格式,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2026-03-03
  • Spring boot JPA實現(xiàn)分頁和枚舉轉換代碼示例

    Spring boot JPA實現(xiàn)分頁和枚舉轉換代碼示例

    這篇文章主要介紹了Spring boot JPA實現(xiàn)分頁和枚舉轉換代碼示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-09-09
  • Java數(shù)據結構之有向圖設計與實現(xiàn)詳解

    Java數(shù)據結構之有向圖設計與實現(xiàn)詳解

    有向圖是具有方向性的圖,由一組頂點和一組有方向的邊組成,每條方向的邊都連著一對有序的頂點。本文為大家介紹的是有向圖的設計與實現(xiàn),需要的可以參考一下
    2022-11-11

最新評論

烟台市| 沁源县| 昌都县| 丽江市| 天气| 华蓥市| 尼玛县| 哈密市| 栖霞市| 樟树市| 来安县| 高安市| 泽州县| 潜山县| 黑山县| 西峡县| 陇南市| 汝州市| 鄂托克旗| 龙泉市| 蒲江县| 三门峡市| 孝昌县| 交城县| 洪泽县| 丘北县| 海口市| 安化县| 卓尼县| 盘锦市| 汕尾市| 临洮县| 广德县| 房产| 延寿县| 翁牛特旗| 营口市| 湖州市| 扶风县| 安庆市| 大兴区|