我有一个发送到另一个函数的lambda函数,我想在lambda中更改一个在lambda范围之外声明的变量。
WebElement textArea ;
BrowserToucher.clickOnWebElement(() -> {
WebElement convPopupOrCard = findElementBy(driver,
conversationCardOrPopup);
return textArea = findSubElementBy(driver, convPopupOrCard,
CardAndPopupTextArea);
}, driver);
BrowserToucher.sendKeys(textArea, driver, text);
我需要更改' textArea' labmda中的var,所以我可以在最后一行使用它的值。
我找到的唯一解决方案是制作“textArea”字样'一个大小为1的数组。 但我真的不明白为什么会这样。 如果有人可以向我解释,请爱。 谢谢!!
答案 0 :(得分:2)
我发现的唯一解决方案是让'textArea'成为一个大小为1的数组但是我真的不明白它为什么会起作用。
它的工作原理是因为捕获的数组本身是 final 或有效的最终(任何值不会改变的变量)。
只要捕获的变量 final 或有效地最终,更改数组的内容就完全没问题了。允许的。
当然,像这样的代码不是线程安全的。因此,理想情况下,在使用此技巧之前,您应该三思而后行。
答案 1 :(得分:1)
如果我正确理解你的问题,如果你记得lambdas只是函数但是没有名字,那么解决方案就不那么难了,所以你可以在括号中传递任何参数,就像你使用' regular&#39 ; java方法。
我找到的唯一解决方案是制作“textArea”字样'一个大小为的数组 但我真的不明白为什么会有效。
在关于java引用的堆栈溢出主题之一中已经很好地描述了这一点。请熟悉它,你会很好地理解它,并且maby为你的问题提出了另一种解决方案:)
答案 2 :(得分:1)
lambda或任何匿名内部类中的变量需要是最终的或有效的最终。
这是因为这些变量被复制到lambda范围。如果引用它们而不是复制它们,当变量超出其声明区域的范围时会出现问题,而lambda范围仍然在执行(想想线程)。
通过定义一个数组,你正在解决这个问题:你强行引用这个值,使用一个有效的最终数组(你初始化数组一次,永远不要改变它)。
最终和有效的最终变量可以安全地复制,因为它们的价值不会改变。
当数组超出范围时没问题,GC仍然保留一个指向lambda范围内的值的指针,并且它不会被垃圾收集,直到lambda和声明区都超出范围。
您可以对列表或任何其他集合执行相同操作。它也适用于包装类。