java:NullPointerExc为什么List直接在其上调用lambda表达式时包含添加的对象。而当lambda是一种方法时

时间:2016-05-08 10:13:12

标签: java javafx lambda

我有JavaFX表单,用户可以选择图像。图像存储在ArrayList中,因为我无法将其直接分配给lambda表达式

中的Image字段
List<ImageByteInfo> imageBinary = new ArrayList<>();
imageBinary.add(null);//for create button test, null is a valid parameter
chooseImage.setOnAction((ActionEvent e) -> {
        File selectedFile = logoChooser.showOpenDialog(stage);
        if (selectedFile != null) {
            Image logo = new Image("file:" + selectedFile.getAbsolutePath());
            imageBinary.clear();
            imageBinary.add(ImageConverter.imageToByteArray(logo));
            System.out.println("list image first entry, INSIDE: " + imageBinary.get(0));//working
            previewLogo.setImage(logo);
        }
    });

所以当用户完成对所有字段的委托时,我调用了一个createButton,当我尝试直接在setOnAction()方法中获取imageBinary List中的存储对象时,问题就在这里。它起作用并获得对象。

createButton.setOnAction((ActionEvent e) -> {
        System.out.println("list image first entry, Outside: " + imageBinary.get(0));
    });

但我想要做的是调用一个方法来保存这个lambda表达式的内容,所以我这样做:

createSchoolButton.setOnAction(createBtnFire(
            nameInput.getText(), ..,
             imageBinary.get(0), 
            .., zipInput.getText()));

这是createBtnFire()

private EventHandler<ActionEvent> createBtnFire(String name, ..
         ImageByteInfo logo, boolean addressEntered, String... addressFields) {
    EventHandler<ActionEvent> createBtn = (ActionEvent e) -> {
        //code..
        entity.setCreationDate(creationDate);//null
        System.out.println(logo);//this print null, so next line throws a NullPointerException
        entity.setImageByteInfoEntity(new ImageByteInfoEntity(logo.getByteImage(), logo.getWidth(), logo.getHeight()));
        //code..
        startUI.continueToMainContent();
    };
    return createBtn;
}

==&GT; entity.setImageByteInfoEntity(..);处的NullPointerException 我确实使列表成为实例变量,仍为null。那么为什么当我不使用lambda表达式的方法时它工作,列表返回对象,当我使用该方法时,它返回null。感谢。

1 个答案:

答案 0 :(得分:1)

这与lambda表达式的范围有关。将lambda表达式视为匿名内部类。当运行定义lambda的代码片段时,将创建此lambda对象。因为它可以保存对lambda表达式之外的变量的引用,所以它们也会被启动。

因此,当使用lambda表达式(如第一个变量)时,将使用对imageBinary的引用,并在运行lambda表达式时访问列表的第一个元素。

在第二种情况下,您定义一个事件处理程序并将imageBinary的第一个元素传递给它,此时该元素仍未初始化。

您可以通过以下方式更改createBtnFire,因此其行为方式相同:

private EventHandler<ActionEvent> createBtnFire(String name, ..
         List<ImageByteInfo> logos, boolean addressEntered, String... addressFields) {
    EventHandler<ActionEvent> createBtn = (ActionEvent e) -> {
        //code..
        entity.setCreationDate(creationDate);//null
        ImageByteInfo logo = logos.get(0);
        System.out.println(logo);
        entity.setImageByteInfoEntity(new ImageByteInfoEntity(logo.getByteImage(), logo.getWidth(), logo.getHeight()));
        //code..
        startUI.continueToMainContent();
    };
    return createBtn;
}