Java8 lambda表达式的实现探索
来源:互联网 发布:北京淘宝摄影 编辑:程序博客网 时间:2024/04/29 04:32
Java8引入了大家千呼万唤的lambda表达式的实现,作为码农,比较好奇的就是如何用以及如何实现的。
如何用就不用多说了,大把地方告诉你怎么用。底层如何实现的就比较有意思了。对我来说要实现lambda表达式,第一反应就是把lambda表达式转化成Java已有的实现,比如内部类,比如动态代理。那么接下来我们看看Java8里面的实现,给出个测试类
//测试类public class Test { public void test(){ String[] atp = {"Rafael Nadal", "Novak Djokovic", "Stanislas Wawrinka", "David Ferrer","Roger Federer", "Andy Murray","Tomas Berdych", "Juan Martin Del Potro"}; List<String> players = Arrays.asList(atp); players.forEach((player) -> System.out.print(player + "; ")); } public static void main(String[] args) { new Test().test(); }}
对应的字节码
//字节码E:\Developer\workspace\Test\bin>javap -v -p test.classClassfile /E:/Developer/workspace/Test/bin/test.class Last modified 2015-12-4; size 2020 bytes MD5 checksum f050d6d2bfd6e395acc86c454044c9ee Compiled from "Test.java"public class Test minor version: 0 major version: 52 flags: ACC_PUBLIC, ACC_SUPERConstant pool: #1 = Class #2 // Test #2 = Utf8 Test #3 = Class #4 // java/lang/Object #4 = Utf8 java/lang/Object #5 = Utf8 <init> #6 = Utf8 ()V #7 = Utf8 Code #8 = Methodref #3.#9 // java/lang/Object."<init>":()V #9 = NameAndType #5:#6 // "<init>":()V #10 = Utf8 LineNumberTable #11 = Utf8 LocalVariableTable #12 = Utf8 this #13 = Utf8 LTest; #14 = Utf8 test #15 = Class #16 // java/lang/String #16 = Utf8 java/lang/String #17 = String #18 // Rafael Nadal #18 = Utf8 Rafael Nadal #19 = String #20 // Novak Djokovic #20 = Utf8 Novak Djokovic #21 = String #22 // Stanislas Wawrinka #22 = Utf8 Stanislas Wawrinka #23 = String #24 // David Ferrer #24 = Utf8 David Ferrer #25 = String #26 // Roger Federer #26 = Utf8 Roger Federer #27 = String #28 // Andy Murray #28 = Utf8 Andy Murray #29 = String #30 // Tomas Berdych #30 = Utf8 Tomas Berdych #31 = String #32 // Juan Martin Del Potro #32 = Utf8 Juan Martin Del Potro #33 = Methodref #34.#36 // java/util/Arrays.asList:([Ljava/lang/Object;)Ljava/util/List; #34 = Class #35 // java/util/Arrays #35 = Utf8 java/util/Arrays #36 = NameAndType #37:#38 // asList:([Ljava/lang/Object;)Ljava/util/List; #37 = Utf8 asList #38 = Utf8 ([Ljava/lang/Object;)Ljava/util/List; #39 = NameAndType #40:#41 // accept:()Ljava/util/function/Consumer; #40 = Utf8 accept #41 = Utf8 ()Ljava/util/function/Consumer; #42 = InvokeDynamic #0:#39 // #0:accept:()Ljava/util/function/Consumer; #43 = InterfaceMethodref #44.#46 // java/util/List.forEach:(Ljava/util/function/Consumer;)V #44 = Class #45 // java/util/List #45 = Utf8 java/util/List #46 = NameAndType #47:#48 // forEach:(Ljava/util/function/Consumer;)V #47 = Utf8 forEach #48 = Utf8 (Ljava/util/function/Consumer;)V #49 = Utf8 atp #50 = Utf8 [Ljava/lang/String; #51 = Utf8 players #52 = Utf8 Ljava/util/List; #53 = Utf8 LocalVariableTypeTable #54 = Utf8 Ljava/util/List<Ljava/lang/String;>; #55 = Utf8 main #56 = Utf8 ([Ljava/lang/String;)V #57 = Methodref #1.#9 // Test."<init>":()V #58 = Methodref #1.#59 // Test.test:()V #59 = NameAndType #14:#6 // test:()V #60 = Utf8 args #61 = Utf8 lambda$0 #62 = Utf8 (Ljava/lang/String;)V #63 = Fieldref #64.#66 // java/lang/System.out:Ljava/io/PrintStream; #64 = Class #65 // java/lang/System #65 = Utf8 java/lang/System #66 = NameAndType #67:#68 // out:Ljava/io/PrintStream; #67 = Utf8 out #68 = Utf8 Ljava/io/PrintStream; #69 = Class #70 // java/lang/StringBuilder #70 = Utf8 java/lang/StringBuilder #71 = Methodref #15.#72 // java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String; #72 = NameAndType #73:#74 // valueOf:(Ljava/lang/Object;)Ljava/lang/String; #73 = Utf8 valueOf #74 = Utf8 (Ljava/lang/Object;)Ljava/lang/String; #75 = Methodref #69.#76 // java/lang/StringBuilder."<init>":(Ljava/lang/String;)V #76 = NameAndType #5:#62 // "<init>":(Ljava/lang/String;)V #77 = String #78 // ; #78 = Utf8 ; #79 = Methodref #69.#80 // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; #80 = NameAndType #81:#82 // append:(Ljava/lang/String;)Ljava/lang/StringBuilder; #81 = Utf8 append #82 = Utf8 (Ljava/lang/String;)Ljava/lang/StringBuilder; #83 = Methodref #69.#84 // java/lang/StringBuilder.toString:()Ljava/lang/String; #84 = NameAndType #85:#86 // toString:()Ljava/lang/String; #85 = Utf8 toString #86 = Utf8 ()Ljava/lang/String; #87 = Methodref #88.#90 // java/io/PrintStream.print:(Ljava/lang/String;)V #88 = Class #89 // java/io/PrintStream #89 = Utf8 java/io/PrintStream #90 = NameAndType #91:#62 // print:(Ljava/lang/String;)V #91 = Utf8 print #92 = Utf8 player #93 = Utf8 Ljava/lang/String; #94 = Utf8 SourceFile #95 = Utf8 Test.java #96 = Utf8 BootstrapMethods #97 = Methodref #98.#100 // java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; #98 = Class #99 // java/lang/invoke/LambdaMetafactory #99 = Utf8 java/lang/invoke/LambdaMetafactory #100 = NameAndType #101:#102 // metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; #101 = Utf8 metafactory #102 = Utf8 (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; #103 = MethodHandle #6:#97 // invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; #104 = Utf8 (Ljava/lang/Object;)V #105 = MethodType #104 // (Ljava/lang/Object;)V #106 = Methodref #1.#107 // Test.lambda$0:(Ljava/lang/String;)V #107 = NameAndType #61:#62 // lambda$0:(Ljava/lang/String;)V #108 = MethodHandle #6:#106 // invokestatic Test.lambda$0:(Ljava/lang/String;)V #109 = MethodType #62 // (Ljava/lang/String;)V #110 = Utf8 InnerClasses #111 = Class #112 // java/lang/invoke/MethodHandles$Lookup #112 = Utf8 java/lang/invoke/MethodHandles$Lookup #113 = Class #114 // java/lang/invoke/MethodHandles #114 = Utf8 java/lang/invoke/MethodHandles #115 = Utf8 Lookup{ public Test(); descriptor: ()V flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #8 // Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 5: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this LTest; public void test(); descriptor: ()V flags: ACC_PUBLIC Code: stack=4, locals=3, args_size=1 0: bipush 8 2: anewarray #15 // class java/lang/String 5: dup 6: iconst_0 7: ldc #17 // String Rafael Nadal 9: aastore 10: dup 11: iconst_1 12: ldc #19 // String Novak Djokovic 14: aastore 15: dup 16: iconst_2 17: ldc #21 // String Stanislas Wawrinka 19: aastore 20: dup 21: iconst_3 22: ldc #23 // String David Ferrer 24: aastore 25: dup 26: iconst_4 27: ldc #25 // String Roger Federer 29: aastore 30: dup 31: iconst_5 32: ldc #27 // String Andy Murray 34: aastore 35: dup 36: bipush 6 38: ldc #29 // String Tomas Berdych 40: aastore 41: dup 42: bipush 7 44: ldc #31 // String Juan Martin Del Potro 46: aastore 47: astore_1 48: aload_1 49: invokestatic #33 // Method java/util/Arrays.asList:([Ljava/lang/Object;)Ljava/util/List; 52: astore_2 53: aload_2 54: invokedynamic #42, 0 // InvokeDynamic #0:accept:()Ljava/util/function/Consumer; 59: invokeinterface #43, 2 // InterfaceMethod java/util/List.forEach:(Ljava/util/function/Consumer;)V 64: return LineNumberTable: line 8: 0 line 9: 17 line 10: 22 line 11: 32 line 12: 44 line 8: 47 line 13: 48 line 14: 53 line 15: 64 LocalVariableTable: Start Length Slot Name Signature 0 65 0 this LTest; 48 17 1 atp [Ljava/lang/String; 53 12 2 players Ljava/util/List; LocalVariableTypeTable: Start Length Slot Name Signature 53 12 2 players Ljava/util/List<Ljava/lang/String;>; public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=1, args_size=1 0: new #1 // class Test 3: dup 4: invokespecial #57 // Method "<init>":()V 7: invokevirtual #58 // Method test:()V 10: return LineNumberTable: line 18: 0 line 19: 10 LocalVariableTable: Start Length Slot Name Signature 0 11 0 args [Ljava/lang/String; private static void lambda$0(java.lang.String); descriptor: (Ljava/lang/String;)V flags: ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC Code: stack=4, locals=1, args_size=1 0: getstatic #63 // Field java/lang/System.out:Ljava/io/PrintStream; 3: new #69 // class java/lang/StringBuilder 6: dup 7: aload_0 8: invokestatic #71 // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String; 11: invokespecial #75 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V 14: ldc #77 // String ; 16: invokevirtual #79 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 19: invokevirtual #83 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 22: invokevirtual #87 // Method java/io/PrintStream.print:(Ljava/lang/String;)V 25: return LineNumberTable: line 14: 0 LocalVariableTable: Start Length Slot Name Signature 0 26 0 player Ljava/lang/String;}SourceFile: "Test.java"BootstrapMethods: 0: #103 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; Method arguments: #105 (Ljava/lang/Object;)V #108 invokestatic Test.lambda$0:(Ljava/lang/String;)V #109 (Ljava/lang/String;)VInnerClasses: public static final #115= #111 of #113; //Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
可以看到Java使用了dymanic invoke ( 54: invokedynamic #42, 0 // InvokeDynamic #0:accept:()Ljava/util/function/Consumer; –> #42 = InvokeDynamic #0:#39 –> 0: #103 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandlesLookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;)调用[BootstrapMethods](https://docs.oracle.com/javase/8/docs/technotes/guides/vm/multiple-language-support.html#defining_bootstrap) ,从bootstrap的实现我们可以知道它的内部实现是调用了java/lang/invoke/LambdaMetafactory的[metafactory](https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/LambdaMetafactory.html#metafactory-java.lang.invoke.MethodHandles.Lookup-java.lang.String-java.lang.invoke.MethodType-java.lang.invoke.MethodType-java.lang.invoke.MethodHandle-java.lang.invoke.MethodType-)。前面3个参数由JVM自动入栈提供,后面3个参数分别是参数以及返回类型( #105 MethodType (Ljava/lang/Object;)V),被调用的lambda函数( #108 MethodHandle invokestatic Test.lambda0:(Ljava/lang/String;)V)以及参数以及参数以及返回实际类型(#109 MethodType (Ljava/lang/String;)V)。对我们这个例子来说就是调用了 private static void lambda
- Java8 lambda表达式的实现探索
- java8的lambda表达式
- Java8新增的Lambda表达式
- Java8引入的lambda表达式
- 一、java8的Lambda表达式
- Java8新增的Lambda表达式
- Java_ Java8 的 lambda 表达式
- 学习java8的lambda表达式
- Java8 探索--Lambda
- Java8的学习计划--lambda表达式的语法
- java8中Lambda表达式的使用
- java8的lambda表达式以及方法引用
- java8 Lambda表达式的学习与测试
- Java8 lambda 表达式的10示例
- JAVA8自定义Lambda表达式的常见使用方法
- Java8 Lambda表达式的快速上手
- java8 Lambda表达式的一些特点
- java8 lambda表达式的简单介绍
- 【bzoj3713】【PA2014】【Iloczyn】【暴力】
- json对象的key有空格的处理方式
- 微信开发-微信支付
- 欢迎使用CSDN-markdown编辑器
- 关于Android Studio中build.gradle文件的gradle路径存在问题
- Java8 lambda表达式的实现探索
- Oracle SQL- MERGE语句
- Android 之popupWindow 在指定位置上的显示
- 点击后立刻反映Toast
- matlab中figure的坐标轴label、title、xticklabel的旋转
- Android酷炫实用的开源框架(UI框架)
- java中的方法重载 overload
- 马哥python培训实战班2016重磅来袭
- easyui扩展datagrid格子移动功能