我不了解lambda的一些事情.
String s = "Hello World";
Function<Integer, String> f = s::substring;
s = null;
System.out.println(f.apply(5));
Run Code Online (Sandbox Code Playgroud)
为什么该f.apply方法仍然有效s = null.毕竟,StringGC应该删除该对象,因为没有指向该对象的指针.
还有一件事,为什么我不需要这里的退货声明?
Function<Integer, String> f = t -> t + "";
Run Code Online (Sandbox Code Playgroud)
rge*_*man 18
在JLS,第15.13.3描述方法引用的运行评估.
方法参考表达式评估的时间比lambda表达式(第15.27.4节)更复杂.当方法引用表达式在:: separator之前具有表达式(而不是类型)时,将立即计算该子表达式.该评价的结果被存储,直到相对应的功能的接口类型的方法被调用; 此时,结果将用作调用的目标引用.这意味着:: separator之前的表达式仅在程序遇到方法引用表达式时计算,并且不会在函数接口类型的后续调用中重新计算.
(大胆强调我的)
基本上,s存储对方法引用的引用以供稍后执行.这里,"Hello World"保存字符串以便稍后执行方法引用.正因为如此,即使你设置s到null方法引用的声明后,但你执行之前Function,它仍然会使用字符串"Hello World".
设置的东西null并不能保证垃圾收集器会收集它,也不能保证它会被立即收集.
此外,在这里,方法参考中仍然有一个引用,所以这里根本不会收集垃圾.
最后,lambda表达式主体有两种形式:表达式和带有(可能)返回语句的语句块.同
Function<Integer, String> f = t -> t + "";
Run Code Online (Sandbox Code Playgroud)
这是一个表达.块语句等效于:
Function<Integer, String> f = t -> { return t + "";};
Run Code Online (Sandbox Code Playgroud)
Jac*_* G. 11
让我们将该方法引用转换为lambda,看看会发生什么:
String s = "Hello World";
Function<Integer, String> f = i -> s.substring(i); // Doesn't compile!
s = null;
System.out.println(f.apply(5));
Run Code Online (Sandbox Code Playgroud)
上面没有编译,因为s在lambda之外被更改,所以它不是最终的.因此,我们可以推断出使用方法引用会缓存s实际使用之前的值.
还有一件事,为什么我在这里不需要返回声明?
当仅指定单个lambda语句时,其值将自动从lambda返回。
Function<Integer, String> f = s::substring;
Run Code Online (Sandbox Code Playgroud)
Java使用按值传递。因此,f是参考副本。
| 归档时间: |
|
| 查看次数: |
753 次 |
| 最近记录: |