从lambda表达式引用的局部变量必须是最终的或有效的final [英] local variables referenced from a lambda expression must be final or effectively final
问题描述
我有一个JavaFX 8程序(适用于JavaFXPorts交叉平台),它实际上是为了做我想做的事情,但却是一步之遥。程序读取文本文件,对行进行计数以建立随机范围,从该范围中选取一个随机数并读取该行以进行显示。
I have a JavaFX 8 program (for JavaFXPorts cross platfrom) pretty much framed to do what I want but came up one step short. The program reads a text file, counts the lines to establish a random range, picks a random number from that range and reads that line in for display.
The error is: local variables referenced from a lambda expression must be final or effectively final
button.setOnAction(e -> l.setText(readln2));
我对java有点新,但似乎我是否使用Lambda或者没有下一个随机行显示在标签l
,我的 button.setOnAction(e - > l.setText(readln2));
行期待一个静态值。
I am a bit new to java but is seems whether I use Lambda or not to have the next random line display in Label l
, my button.setOnAction(e -> l.setText(readln2));
line is expecting a static value.
我每次按下屏幕上的按钮时,有什么想法可以调整我所拥有的内容,只需显示var readln2的下一个值?
Any ideas how I can tweak what I have to simply make the next value of the var readln2 display each time I press the button on the screen?
提前致谢,这是我的代码:
Thanks in advance and here is my code:
String readln2 = null;
in = new BufferedReader(new FileReader("/temp/mantra.txt"));
long linecnt = in.lines().count();
int linenum = rand1.nextInt((int) (linecnt - Low)) + Low;
try {
//open a bufferedReader to file
in = new BufferedReader(new FileReader("/temp/mantra.txt"));
while (linenum > 0) {
//read the next line until the specific line is found
readln2 = in.readLine();
linenum--;
}
in.close();
} catch (IOException e) {
System.out.println("There was a problem:" + e);
}
Button button = new Button("Click the Button");
button.setOnAction(e -> l.setText(readln2));
// error: local variables referenced from a lambda expression must be final or effectively final
推荐答案
您只需将 readln2
的值复制到 final
变量中: / p>
You can just copy the value of readln2
into a final
variable:
final String labelText = readln2 ;
Button button = new Button("Click the Button");
button.setOnAction(e -> l.setText(labelText));
如果你想每次都获取一条新的随机行,你可以缓存感兴趣的行和在事件处理程序中选择一个随机的:
If you want to grab a new random line each time, you can either cache the lines of interest and select a random one in the event handler:
Button button = new Button("Click the button");
Label l = new Label();
try {
List<String> lines = Files.lines(Paths.get("/temp/mantra.txt"))
.skip(low)
.limit(high - low)
.collect(Collectors.toList());
Random rng = new Random();
button.setOnAction(evt -> l.setText(lines.get(rng.nextInt(lines.size()))));
} catch (IOException exc) {
exc.printStackTrace();
}
// ...
或者你可以重新阅读事件处理程序中的文件。第一种技术(更快)但可能消耗大量内存;第二个不会将任何文件内容存储在内存中,但每次按下按钮时都会读取文件,这可能会使UI无响应。
Or you could just re-read the file in the event handler. The first technique is (much) faster but could consume a lot of memory; the second doesn't store any of the file contents in memory but reads a file each time the button is pressed, which could make the UI unresponsive.
你得到的错误基本上告诉你出了什么问题:你可以从lambda表达式中访问的唯一局部变量是 final
(声明 final
,这意味着它们必须被分配一个值一次)或有效最终(这基本上意味着你可以使它们最终而不需要对代码进行任何其他更改)。
The error you got basically tells you what was wrong: the only local variables you can access from inside a lambda expression are either final
(declared final
, which means they must be assigned a value exactly once) or "effectively final" (which basically means you could make them final without any other changes to the code).
您的代码无法编译,因为 readln2
被多次赋值(在循环内),因此无法声明 final
。因此,您无法在lambda表达式中访问它。在上面的代码中,lambda中访问的唯一变量是 l
,行
和 rng
,这些都是有效的最终,因为它们只被赋值一次。(你可以将它们声明为final,代码仍然可以编译。)
Your code fails to compile because readln2
is assigned a value multiple times (inside a loop), so it cannot be declared final
. Thus you can't access it in a lambda expression. In the code above, the only variables accessed in the lambda are l
, lines
, and rng
, which are all "effectively final` as they are assigned a value exactly once. (You can declare them final and the code would still compile.)
这篇关于从lambda表达式引用的局部变量必须是最终的或有效的final的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!