正如我所知,对于内部和无限类,外部作用域的变量存储在生成的字节码中(例如OuterClass $ 1.class)。 我想知道下一个例子存储变量的位置:
padding='SAME'
Lambda被翻译为方法,而不是类。是否意味着对于这2个调用将生成2个单独的方法?
答案 0 :(得分:7)
这个表达式x -> x * elem;
将去除静态方法,如下所示:
private static Integer lambda$curring$0(int x, int y){
return x*y;
}
因为lambda中的capturing
变量是elem
,所以lambda被认为是stateful lambda
。
另一方面,您的map
操作需要java.util.Function
的实际实例 - 并且在运行时生成 ,如下所示:
final class Test2$$Lambda$1 implements java.util.function.Function {
private final Integer arg$1;
private Test2$$Lambda$1(Integer arg$1){
this.arg$1 = arg$1;
}
// static factory method
private static java.util.function.Function get$Lambda(Integer i){
return new Test2$$Lambda$1(i); // instance of self
}
public Integer apply(Integer x) {
return YourClass.lambda$curring$0(this.arg$1, x);
}
}
在调用Function.apply
之前(在地图操作中),通过静态工厂方法Test2$$Lambda$1
生成get$Lambda
的新实例。这是必要的"携带" elem
变量。
因为每次调用地图时都会创建一个新实例。
由于您的Stream有五个初始元素,因此将为这两个map
操作创建10个实例。
但一般这是一个可能很容易在某一天改变的实施细节 - 所以不要依赖它。此短期实例的创建和收集(通过垃圾收集器)非常便宜,几乎不会影响您的应用程序。
答案 1 :(得分:3)
每次调用curring(..)
方法时,都会创建一个新对象。所以,是的,你将有2个对象。
这是因为你的lambda不是无状态的,也就是说它不能单独使用它。它需要捕获外部变量elem
。
如果您的lambda中使用了2
这样的固定数字而不是elem
:
public Function<Integer, Integer> curring() {
return x -> x * 2;
}
你的lambda将是无国籍的。它不会捕获任何外部变量。在这种情况下,你的lambda将是一个多次调用的单例。
请注意,此行为与JVM有关,而上述内容来自HotSpot JVM。
此处有更多信息:Does a lambda expression create an object on the heap every time it's executed?