Java中的闭包 [英] Closures in Java

查看:53
本文介绍了Java中的闭包的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此示例是JavaScript(我不知道JS)中闭包的模拟:

This example is a simulation of closures in JavaScript (I don't know JS):

public class Lambda {

    public static void main(String[] args) {
        Supplier generator = Lambda.generator();
        System.out.println(generator.get());
        System.out.println(generator.get());
        System.out.println(generator.get());
    }

    static Supplier<Integer> generator() {
        Integer arr[] = {0};
        return () -> ++arr[0];
    }
}

输出为1 23。
通常,局部方法变量的寿命受到方法执行时间的限制。但是在这种情况下,对 arr [] 的引用存储在某个位置。那么它存储在哪里,又是什么呢?

The output is 1 2 3. Usually the lifespan of local method variables is limited by the method execution time. But in this case the reference to arr[] is stored somewhere. So where is it stored and what's under the hood?

推荐答案

Java语言规范(§15.27.4)说:

The Java Language Specification (§15.27.4) says:


lambda表达式的值是对具有以下属性的类的实例的引用:

The value of a lambda expression is a reference to an instance of a class with the following properties:


  • 该类实现目标功能接口类型...

因此,lambda定义了一个类,就像一个匿名类声明会执行此操作,并且lambda表达式会导致对该类实例的引用。对 arr 的引用由属于该实例的综合 final 字段保存。

So the lambda defines a class, much like an anonymous class declaration does, and the lambda expression results in a reference to an instance of that class. The reference to arr is held by a synthetic final field belonging to that instance.

以下是在JShell REPL中使用反射的示例,以演示具有合成字段的lambda:

Here's an example using reflection in the JShell REPL, to demonstrate a lambda with a synthetic field:

> class A { static Runnable a(int x) { return () -> System.out.println(x); } }
| created class A

> Runnable r = A.a(5);
r ==> A$$Lambda$15/1476394199@31ef45e3

> import java.lang.reflect.Field;

> Field f = r.getClass().getDeclaredFields()[0];
f ==> private final int A$$Lambda$15/1476394199.arg$1

> f.setAccessible(true);

> f.get(r)
$6 ==> 5

这篇关于Java中的闭包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆