由于工作原因,公司使用JDK7的版本, JDK8几乎没有使用到。
之前曾经了解到Lambda 表达式, function功能性函数,ConcurrentHashMap等在JDK8了升级优化等。
中文版 jdk8官方说明:https://www.oracle.com/cn/java/technologies/javase/8-whats-new.html
仅仅对相关重要的特性做一下学习。
1. Lambda 表达式, 相信凡是使用过JDK8的人,应该对这个耳熟能详了。
但Lambda 的实现原理呢?
先来一个demo , 其中 (o1, o2) -> o1.compareTo(o2), 就是一个Lambda表达式。
public class LambdaTest {
private volatile int age = 1;
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(10);
list.add(3);
list.add(2);
list.add(18);
Collections.sort(list, (o1, o2) -> o1.compareTo(o2));
}
}
我们来看一下, 这个测试类,生成的字节码是什么。通过
javap -c -p LambdaTest.class 得到下面信息。
* <pre>
* Compiled from "LambdaTest.java"
* public class com.hjb.learning.jdk8.LambdaTest {
* public com.hjb.learning.jdk8.LambdaTest();
* Code:
* 0: aload_0
* 1: invokespecial #1 // Method java/lang/Object."<init>":()V
* 4: return
*
* public static void main(java.lang.String[]);
* Code:
* 0: new #2 // class java/util/ArrayList
* 3: dup
* 4: invokespecial #3 // Method java/util/ArrayList."<init>":()V
* 7: astore_1
* 8: aload_1
* 9: iconst_1
* 10: invokestatic #4 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
* 13: invokeinterface #5, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
* 18: pop
* 19: aload_1
* 20: bipush 10
* 22: invokestatic #4 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
* 25: invokeinterface #5, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
* 30: pop
* 31: aload_1
* 32: iconst_3
* 33: invokestatic #4 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
* 36: invokeinterface #5, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
* 41: pop
* 42: aload_1
* 43: iconst_2
* 44: invokestatic #4 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
* 47: invokeinterface #5, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
* 52: pop
* 53: aload_1
* 54: bipush 18
* 56: invokestatic #4 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
* 59: invokeinterface #5, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
* 64: pop
* 65: aload_1
* 66: invokedynamic #6, 0 //这一行注意了 // InvokeDynamic #0:compare:()Ljava/util/Comparator;
* 71: invokestatic #7 // Method java/util/Collections.sort:(Ljava/util/List;Ljava/util/Comparator;)V
* 74: return
*
* private static int lambda$main$0(java.lang.Integer, java.lang.Integer);
* Code:
* 0: aload_0
* 1: aload_1
* 2: invokevirtual #8 // Method java/lang/Integer.compareTo:(Ljava/lang/Integer;)I
* 5: ireturn
* }
*
*
* </pre>
可以发现,在反编译之后出现了invokedynamic指令,以及一个lambda$main$0静态方法, 静态方法是比较2个Integer信息。
所以可以大胆的猜测lambda表达式,底层是通过invokedynamic实现的。
其实可以通过在运行是加上-Djdk.internal.lambda.dumpProxyClasses=path,生成lambda内部类的方式,看看究竟。
* <pre>
* 使用jad反编译工具之后, lambda实际生成的是一个final的内部类。
* final class LambdaTest$$Lambda$1 implements Comparator {
*
* public int compare(Object obj, Object obj1) {
* return LambdaTest.lambda$main$0((Integer) obj, (Integer) obj1);
* }
*
* private LambdaTest$$Lambda$1() {
* }
* }
*
* </pre>
这样看着貌似很明显了, (o1, o2) -> o1.compareTo(o2)生成了一个实现Comparator的类, 类的主题逻辑就是调用之前产生的
lambda$main$0的静态方法。
这样就形成了一个思路: lambda生成了一个类,同时也生成了一个静态方法。 然后应用程序在调用lambda对应代码的时候,其实就是调用的这个类,然后调用到静态方法。
以上这些都是JDK给我们自动生成了。当然这个仅仅是站在巨人的肩膀上,开发人员可以这样简单的理解。
lambda最核心的思想是invokedynamic指令的应用。 如果想要了解怎么生成这些信息的,建议先了解invokedynamic。
然后再看一下LambdaMetafactory类,膜拜下牛人的设计思想和代码理念