- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我得到了以下代码,它是从我在 Java 程序中的实际实现中抽象出来的:
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String line;
while ((line = bufferedReader.readLine()) != null) {
String lineReference = line;
runLater(() -> consumeString(lineReference));
}
line
时,我需要为 lambda 表达式使用引用副本。我得到:
Local variables referenced from a lambda expression must be final or effectively final
line
在这里实际上是最终的,因为它只在循环中获得分配而没有其他地方。
最佳答案
So I would say
line
is effectively final here, as it only gets the assignment in the loop and nowhere else.
I get: 'Local variables referenced from a lambda expression must be final or effectively final'. It seems rather awkward to me.
runLater(...)
.当 lambda 最终执行时,
line
的哪个值它应该使用吗?它在创建 lambda 时拥有的值,还是在 lambda 执行时拥有的值?
line
是一个静态字段,这很容易,因为 lambda 没有要捕获的状态。 lambda 可以在需要时读取字段的当前值,就像任何其他代码一样。 line
是一个实例字段,这也很容易。 lambda 可以在每个 lambda 对象中的私有(private)隐藏字段中捕获对对象的引用,并访问 line
场通过。 line
是方法中的局部变量(如您的示例中所示),这突然变得不容易。在实现级别,lambda 表达式 is in a completely different method ,并且外部代码没有简单的方法来共享对仅存在于一种方法中的变量的访问。 line
变量可以有任何值或没有定义的值,而且几乎肯定不会有你想要的值。所以在实践中你仍然需要单独的、不变的
lineReference
多变的!唯一的区别是编译器不会要求您这样做,因此它允许您编写损坏的代码。由于 lambda 最终可以在不同的线程上执行,这也会为局部变量引入微妙的并发性和线程可见性复杂性,这将需要语言允许
volatile
局部变量上的修饰符,以及其他麻烦。
final
来拒绝整个困惑局面。 (或有效地最终)。这样,lambda 可以在创建 lambda 时捕获局部变量的值,并且不需要担心检测更改,因为它知道不可能有任何更改。
This is something the compiler could also figure out by itself
lineReference
变量
对编译器绝对没有好处 ,它可以轻松捕获
line
的当前值用于在每个 lambda 对象创建时的 lambda 中。但是由于 lambda 不会检测到变量的变化(由于上述原因,这将是不切实际和不可取的),字段捕获和局部变量捕获之间的细微差别会令人困惑。 “最终或有效最终”规则是为了程序员的利益:它阻止您想知道为什么对变量的更改不会出现在 lambda 中,因为您根本无法更改它们。这是没有该规则会发生的情况的示例:
String field = "A";
void foo() {
String local = "A";
Runnable r = () -> System.out.println(field + local);
field = "B";
local = "B";
r.run(); // output: "BA"
}
lineReference
实际上是最终的。它的值在其生命周期内只分配一次,在每次循环迭代结束时超出范围之前,这就是您可以在 lambda 中使用它的原因。
line
可以对循环进行另一种安排在循环体内:
for (;;) {
String line = bufferedReader.readLine();
if (line == null) break;
runLater(() -> consumeString(line));
}
line
现在在每次循环迭代结束时超出范围。每次迭代实际上都有一个新变量,只分配一次。 (但是,在低级别上,变量仍然存储在同一个 CPU 寄存器中,因此不必重复“创建”和“销毁”。我的意思是,在内部声明变量很高兴没有额外成本像这样的循环,所以没问题。)
x
在 lambda 内访问,读取行为之间会有差异
x
(捕获
x
的最终值)和
this.x
(捕获
this
的最终值,看到其字段
x
发生变化)。语言设计很难。
关于java - 在这种情况下,为什么我不能从 lambda 中引用变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24742584/
可以使用 lambda 和函数创建有序对(Lisp 中的缺点),如 Use of lambda for cons/car/cdr definition in SICP 所示。 它也适用于 Python
我正在尝试从另一个调用一个 AWS lambda 并执行 lambda 链接。这样做的理由是 AWS 不提供来自同一个 S3 存储桶的多个触发器。 我创建了一个带有 s3 触发器的 lambda。第一
根据以下源代码,常规 lambda 似乎可以与扩展 lambda 互换。 fun main(args: Array) { val numbers = listOf(1, 2, 3) f
A Tutorial Introduction to the Lambda Calculus 本文介绍乘法函数 The multiplication of two numbers x and y ca
我想弄清楚如何为下面的表达式绘制语法树。首先,这究竟是如何表现的?看样子是以1和2为参数,如果n是 0,它只会返回 m . 另外,有人可以指出解析树的开始,还是一个例子?我一直找不到一个。 最佳答案
在 C++0x 中,我想知道 lambda 函数的类型是什么。具体来说: #include type1 foo(int x){ return [x](int y)->int{return x * y
我在其中一个职位发布中看到了这个问题,它询问什么是 lambda 函数以及它与高阶函数的关系。我已经知道如何使用 lambda 函数,但不太自信地解释它,所以我做了一点谷歌搜索,发现了这个:What
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
Evaluate (((lambda(x y) (lambda (x) (* x y))) 5 6) 10) in Scheme. 我不知道实际上该怎么做! ((lambda (x y) (+ x x
我正在处理 MyCustomType 的实例集合如下: fun runAll(vararg commands: MyCustomType){ commands.forEach { it.myM
Brian 在他对问题 "Are side effects a good thing?" 的论证中的前提很有趣: computers are von-Neumann machines that are
在 Common Lisp 中,如果我希望两个函数共享状态,我将按如下方式执行 let over lambda: (let ((state 1)) (defun inc-state () (in
Evaluate (((lambda(x y) (lambda (x) (* x y))) 5 6) 10) in Scheme. 我不知道实际上该怎么做! ((lambda (x y) (+ x x
作为lambda calculus wiki说: There are several possible ways to define the natural numbers in lambda cal
我有一个数据类,我需要初始化一些 List .我需要获取 JsonArray 的值(我使用的是 Gson)。 我做了这个函数: private fun arrayToList(data: JsonAr
((lambda () )) 的方案中是否有简写 例如,代替 ((lambda () (define x 1) (display x))) 我希望能够做类似的事情 (empty-lam
我在 Java library 中有以下方法: public void setColumnComparator(final int columnIndex, final Comparator colu
我正在研究一个函数来计算国际象棋游戏中棋子的有效移动。 white-pawn-move 函数有效。当我试图将其概括为任一玩家的棋子 (pawn-move) 时,我遇到了非法函数调用。我已经在 repl
考虑这段代码(在 GCC 和 MSVC 上编译): int main() { auto foo = [](auto p){ typedef decltype(p) p_t;
我正在阅读一个在 lambda 内部使用 lambda 的片段,然后我想通过创建一个虚拟函数来测试它,该函数从文件中读取然后返回最大和最小数字。 这是我想出来的 dummy = lambda path
我是一名优秀的程序员,十分优秀!