有没有办法让Java lambda表达式不能引用封闭对象?

ATr*_*bka 9 java lambda

当使用lambda表达式时,Java实际上会创建一个匿名(非静态)类.非静态内部类始终包含其封闭对象的引用.

当从另一个库中调用此lambda表达式时,该表达式可能在另一个进程中调用lambda,调用因未找到类异常而崩溃,因为它无法在另一个进程中找到封闭对象的类.

考虑这个例子:

public class MyClass {
    public void doSomething() {
        remoteLambdaExecutor.executeLambda(value -> value.equals("test"));
    }
}
Run Code Online (Sandbox Code Playgroud)

Java将创建一个匿名内部类,它实现某些功能接口并将其作为参数传递给executeLambda().然后remoteLambdaExecutor将整个进程中的匿名类进行远程运行.远程进程对MyClass一无所知,会抛出

java.lang.ClassNotFoundException: MyClass
Run Code Online (Sandbox Code Playgroud)

因为它需要MyClass用于封闭对象引用.

我总是可以使用API​​所期望的功能接口的静态实现,但这会破坏目的并且不会使用lambda功能.

有没有办法用lambda表达式来解决它?

更新:我不能使用静态类,除非它以某种方式导出到其他进程.

Hol*_*ger 6

你最初的前提是错误的.JRE 不会生成匿名内部类.它可能会生成一个类,但如果您的lambda表达式不访问this或者static该类的非成员,则它不会保留对该this实例的引用.

但是,这并不意味着课程本身是不必要的.由于该类承载lambda表达式的代码,因此总是需要它.在这方面,使用static嵌套类的解决方案不会改变它的任何内容,因为它static是执行代码所需的嵌套类.

如果不传输包含要执行的代码的类,则无法将对象传输到远程执行工具(除非该类已存在于远程站点).

  • 换句话说,Java lambda 更像是一个 C++ 函数指针,而不是 Lisp lambda。Java lambda 会告诉您要运行哪些代码,但实际上并不包含该代码。我没有意识到这一点。 (2认同)