例如,在匿名内部类的情况下,传递(匿名)对象引用并执行该对象的方法。
Lambdas是将在需要时执行的代码块。
遇到lambdas时JVM中会发生什么? JVM在哪里存储与lambdas相关的代码块(Heap:Young,Old或Permanent Generation)?
我尝试搜索,我得到了使用lambdas的语法但是无法理解JVM中发生的事情,因为在JAVA中一切都是基于对象的。
我不会浪费时间思考lambda表达式是否违反OO原则。它的目标是增加语言的力量而不是编写OO代码,我不知道lambdas如何违反封装,继承或多态。
这个article解释了Java如何处理lambda表达式:
Lambda表达式的有趣之处在于,从JVM的角度来看,它们是完全不可见的。它没有匿名函数或Lambda表达式的概念。它只知道字节码是严格的OO规范。由语言及其编译器的制造商在这些约束下工作以创建更新,更高级的语言元素。
考虑以下代码:
List names = Arrays.asList("1", "2", "3");
Stream lengths = names.stream().map(name -> name.length());
...它很简单地通过加载名称var并调用其
.stream()
方法开始,但随后它做了一件非常优雅的事情。它不使用创建将包装Lambda函数的新对象,而是使用Java 7中添加的新invokeDynamic
指令将此调用站点动态链接到实际的Lambda函数。
aload_1 //load the names var
// call its stream() func
invokeinterface java/util/List.stream:()Ljava/util/stream/Stream;
//invokeDynamic magic!
invokedynamic #0:apply:()Ljava/util/function/Function;
//call the map() func
invokeinterface java/util/stream/Stream.map:
(Ljava/util/function/Function;)Ljava/util/stream/Stream;
InvokeDynamic
是Java 7中添加的一条指令,它使JVM不那么严格,并允许动态语言在运行时绑定符号,而不是在JVM编译代码时静态地执行所有链接。
Lambda代码
aload_0
invokevirtual java/lang/String.length:()
invokestatic java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
areturn
Lambda表达式不会被转换为anonymous inner classes
,它们使用Java 7中引入的invoke dynamic来执行函数方法。 Check this out。
他们违反了OOP
吗?我不认为你应该关心。 Lambdas使您的代码更简洁,更易于理解,并且“更容易”并行化。这就是你应该关心的。
来自Brain Goetz评论:
我们没有得到编写面向对象程序或功能程序的报酬,我们得到报酬编写工作程序。
invokedynamic
字节码编译Lambda表达式。请参阅more details规范负责人的Lambda Expressions JSR。