Java 中指向 String 方法的函数指针

2022-09-03 04:34:04

我不明白lambda的几件事。

String s = "Hello World";       
Function<Integer, String> f = s::substring;
s = null;
System.out.println(f.apply(5));

如果 出现 ,为什么该方法仍然有效。毕竟,GC 应删除该对象,因为没有指向该对象的指针。f.applys = nullString

还有一件事,为什么我在这里不需要退货声明?

Function<Integer, String> f = t -> t + "";

答案 1

JLS 第 15.13.3 节描述了方法引用的运行时评估。

方法引用表达式计算的时间比 lambda 表达式的计时更复杂 (§15.27.4)。当方法引用表达式在 :: 分隔符之前有一个表达式(而不是类型)时,将立即计算该子表达式。在调用相应功能接口类型的方法之前,将存储计算结果;此时,结果将用作调用的目标引用。这意味着仅当程序遇到方法引用表达式时,才会计算 :: 分隔符前面的表达式,并且在对功能接口类型的后续调用时不会重新计算。

(粗体强调我的)

基本上,对方法引用的引用被存储起来供以后执行。此处保存该字符串,以便以后执行方法引用。正因为如此,即使设置为声明后的方法引用,但在执行之前,它仍然会使用字符串。s"Hello World"snullFunction"Hello World"

将某些内容设置为 并不能保证垃圾回收器将收集它,也不能保证立即收集它。null

此外,在这里,方法引用中仍然有一个引用,因此它在这里根本不会被垃圾收集。

最后,lambda 表达式主体有 2 种形式:一个表达式和一个带有 return 语句的语句块。跟

Function<Integer, String> f = t -> t + "";

这是一种表达。块语句等效项为:

Function<Integer, String> f = t -> { return t + "";};

答案 2

让我们将该方法引用转换为 lambda,看看会发生什么:

String s = "Hello World";
Function<Integer, String> f = i -> s.substring(i); // Doesn't compile!
s = null;
System.out.println(f.apply(5));

上述内容无法编译,因为正在 lambda 外部进行更改,因此它不是有效的最终结果。因此,我们可以推断出,使用方法引用会在实际使用之前缓存 的值。ss

请参见:方法引用缓存在 Java 8 中是一个好主意吗?


推荐