首页 > 解决方案 > 迭代包含 mouseEvent 操作的 for 循环时发生异常

问题描述

当我使用包含通过radioButtons 的mouseEvent 操作的NORMAL for 循环进行迭代时,会出现以下异常消息。

消息:线程“JavaFX 应用程序线程”中的异常 java.lang.ArrayIndexOutOfBoundsException

但是当我使用for-each循环进行迭代时,没有问题!

请帮助我,谢谢

相关代码部分:


 HBox p1 = new HBox();
       
        RadioButton Red = new RadioButton("RED");
        RadioButton Blue = new RadioButton("Blue");
        RadioButton Black = new RadioButton("Black");
        
          ToggleGroup tg = new ToggleGroup(); 
        
          Red.setToggleGroup(tg);
        Blue.setToggleGroup(tg);
         Black.setToggleGroup(tg);
         
        
        RadioButton [] array = {Red,Blue,Black};
        
        p1.getChildren().addAll(Red,Blue,Black);
 
     
     i = 0;
     for(i = 0; i< array.length; i++){
         
         array[i].setOnAction(e->{
         
             System.out.println(array[i].getText());
         });
         
     }

标签: for-loopjavafxforeachindexoutofboundsexception

解决方案


我猜,因为您的问题不完整,您将循环索引设置i为实例变量,出于某种原因。即你有类似的东西:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.RadioButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class Demo extends Application {
    
    // Guessing:
    private int i ;

    @Override
    public void start(Stage primaryStage) throws Exception {
        HBox p1 = new HBox();

        RadioButton red = new RadioButton("RED");
        RadioButton blue = new RadioButton("Blue");
        RadioButton black = new RadioButton("Black");

        ToggleGroup tg = new ToggleGroup();

        red.setToggleGroup(tg);
        blue.setToggleGroup(tg);
        black.setToggleGroup(tg);

        RadioButton[] array = { red, blue, black };

        p1.getChildren().addAll(red, blue, black);

        i = 0;
        for (i = 0; i < array.length; i++) {

            array[i].setOnAction(e -> {

                System.out.println(array[i].getText());
            });

        }
        
        Scene scene = new Scene(p1, 400, 250);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        Application.launch(args);
    }

}

iDemo实例的一个属性(即在其start()上调用的应用程序实例)。在该start()方法中,每次迭代循环时i都会初始化并递增。当不再小于(即)时,循环退出,所以当循环退出时,。0forforiarray.length3fori==3

因此,当您按下其中一个按钮时,代码

System.out.println(array[i].getText());

被执行。自循环完成以来,的值i没有改变for,所以这相当于

System.out.println(array[3].getText());

这会抛出IndexOutOfBoundsException, 因为数组中的值索引是0,12。事实上,完整的错误信息是

Exception in thread "JavaFX Application Thread" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3

相反,您需要为循环中的索引使用局部变量:

    for (int i = 0; i < array.length; i++) {

        array[i].setOnAction(e -> { /* ... */ });

    }

现在的问题是事件处理程序中的 lambda 表达式无法访问局部变量i,因为它不是final(或“实际上是最终的”)。解决方案是在最终变量中“捕获”i循环每次迭代的值:

    for (int i = 0; i < array.length; i++) {
        final int index = i ;
        array[i].setOnAction(e -> {
            System.out.println(array[index].getText());
        });

    }

当然,您实际上并不需要索引;您只需要数组的元素,因此您可以捕获它:

    for (int i = 0; i < array.length; i++) {
        final RadioButton button = array[i] ;
        button.setOnAction(e -> {
            System.out.println(button.getText());
        });
    }

此代码与以下代码完全相同(在某种意义上,编译器将以下内容转换为相同的内容):

    for (RadioButton button : array) {
        button.setOnAction(e -> {
            System.out.println(button.getText());
        });
    }

这是迄今为止for循环的首选形式。

这是代码的完全清理和工作版本:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.RadioButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class Demo extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {
        HBox p1 = new HBox();

        RadioButton red = new RadioButton("RED");
        RadioButton blue = new RadioButton("Blue");
        RadioButton black = new RadioButton("Black");

        ToggleGroup tg = new ToggleGroup();
        RadioButton[] buttons = { red, blue, black };

        tg.getToggles().setAll(buttons);
        p1.getChildren().addAll(buttons);

        for (RadioButton button : buttons) {
            button.setOnAction(e -> {
                System.out.println(button.getText());
            });
        }
        
        Scene scene = new Scene(p1, 400, 250);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        Application.launch(args);
    }

}

推荐阅读