簡體   English   中英

java:是否可以為按鈕數組設置 lambda 表達式是一個 for 循環? 如果是這樣怎么辦?

[英]java: Is it possible to set a lambda expression for an array of Buttons is a for loop? If so how?

我希望能夠做這樣的事情:

for(i = 0; i < 10; i++) {
    //if any button in the array is pressed, disable it.
    button[i].setOnAction( ae -> { button[i].setDisable(true) } );
}

但是,我收到一條錯誤消息,指出"local variables referenced from a lambda expression must be final or effectively final" 我怎么還能像上面的代碼那樣做(如果可能的話)? 如果做不到,應該怎么做才能得到類似的結果?

正如錯誤消息所說,從 lambda 表達式引用的局部變量必須是最終的或有效最終的(“有效最終”意味着編譯器可以為您使其成為最終的)。

簡單的解決方法:

for(i = 0; i < 10; i++) {
    final int ii = i;
    button[i].setOnAction( ae -> { button[ii].setDisable(true) } );
}

由於您使用的是 lambda,您還可以從 Java 8 的其他功能(如流)中受益。

例如, IntStream

支持順序和並行聚合操作的原始整數值元素序列。 這是 Stream 的 int 原始特化。

可用於替換 for 循環:

IntStream.range(0,10).forEach(i->{...});

所以現在你有一個可以用於你的目的的索引:

IntStream.range(0,10)
         .forEach(i->button[i].setOnAction(ea->button[i].setDisable(true)));

您也可以從數組生成流:

 Stream.of(button).forEach(btn->{...});

在這種情況下,您將沒有索引,因此正如@shmosel 所建議的,您可以使用事件的來源:

Stream.of(button)
          .forEach(btn->btn.setOnAction(ea->((Button)ea.getSource()).setDisable(true)));    

編輯

正如@James_D 所暗示的,這里沒有必要貶低:

Stream.of(button)
      .forEach(btn->btn.setOnAction(ea->btn.setDisable(true)));

在這兩種情況下,您還可以從並行操作中受益:

IntStream.range(0,10).parallel()
         .forEach(i->button[i].setOnAction(ea->button[i].setDisable(true)));

Stream.of(button).parallel()
          .forEach(btn->btn.setOnAction(ea->btn.setDisable(true)));

使用Event來獲取源Node

for(int i = 0; i < button.length; i++)
{
     button[i].setOnAction(event ->{
         ((Button)event.getSource()).setDisable(true);
     });
}

Lambda 表達式實際上就像一個在流上工作的匿名方法。 為了避免任何不安全的操作,Java 規定在 lambda 表達式中不能訪問可以修改的外部變量。

為了解決這個問題,

最終 int index=button[i]; 並在 lambda 表達式中使用 index 而不是i

您說如果按下按鈕,但在您的示例中,列表中的所有按鈕都將被禁用。 嘗試將偵聽器與每個按鈕相關聯,而不僅僅是禁用它。

對於邏輯,你的意思是這樣的:

Arrays.asList(buttons).forEach(
        button -> button.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                button.setEnabled(false);

            }
}));

我也喜歡 Sedrick 的回答,但您必須在循環中添加一個動作偵聽器。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM