启动 JavaFX 应用程序时的内部 NPE [英] Internal NPE when launching JavaFX Application

查看:29
本文介绍了启动 JavaFX 应用程序时的内部 NPE的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以基本上我开始了一个虚拟的 JavaFX 项目只是为了为我的实际问题实现一个简约的例子.但是现在我什至无法再运行那个简约的项目,也没有收到足够的错误信息来真正自己用谷歌搜索出来.所以现在,当我运行代码时,我收到给定的错误堆栈,这并没有引导我到任何地方.

So basically I began a dummy JavaFX project just to achieve a minimalistic example for my actual problem. But now I am not even able to run that minimalistic project anymore and do not receive enough error information to actually google it myself out. So right now, when I run the code, I receive the given error stack, which does not lead me anywhere.

我正在使用 IntelliJ.JavaFX 库设置正确,VM 选项设置为:--module-path "C:Program FilesJavajavafx-sdk-11.0.2lib" --add-modules javafx.controls,javafx.fxml

I am using IntelliJ. JavaFX libraries are set correctly and VM Options set to: --module-path "C:Program FilesJavajavafx-sdk-11.0.2lib" --add-modules javafx.controls,javafx.fxml

最重要的是,当我运行代码时,这些错误会在控制台中弹出,但应用程序似乎仍在运行,因为我需要按下 IntelliJ 的红色停止按钮才能真正停止它.

On top, when I run the code, those errors pop up in console, but the application seems to still be running, because I need to press the Red Stop Button of IntelliJ to actually stop it.

有人猜到这里出了什么问题吗?我没有足够的经验来跟踪这些错误,因为它们不是指向我的代码,而是指向一些 Deep Java 代码.

Has anyone some guess, what goes wrong here? I am not experienced enough to follow those errors, since they do not point into my code, but rather into some Deep Java code.

例外:

Exception in thread "main" java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.NullPointerException
    at java.base/java.lang.reflect.Method.invoke(Method.java:559)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
    ... 5 more

Main.java:

package sample;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import java.io.IOException;

public class Main extends Application {

    private Stage rootStage;
    public BorderPane mainWindow;
    public AnchorPane left;
    public AnchorPane bottom;

    @Override
    public void start(Stage primaryStage) throws Exception {

        this.rootStage = primaryStage;
        loadMainWindow();

    }

    public void loadMainWindow() throws IOException {

            FXMLLoader loaderMainWindow = new FXMLLoader(Main.class.getResource("MainWindow.fxml"));
            mainWindow = loaderMainWindow.load();

            FXMLLoader loaderLeft = new FXMLLoader(Main.class.getResource("Left.fxml"));
            left = loaderLeft.load();


            mainWindow.setLeft(left);
            //mainWindow.setBottom(bottom);


        Scene scene = new Scene(mainWindow);
        rootStage.setScene(scene);
        rootStage.show();

    }

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

MainWindow.fxml:

MainWindow.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.BorderPane?>


<BorderPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.MainWindowController" />

主窗口控制器:

package sample;

import javafx.fxml.Initializable;

import java.net.URL;
import java.util.ResourceBundle;



public class MainWindowController implements Initializable {

    private Main main;

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {

    }

    public void setMain(Main main) {
        this.main = main;
    }
}

左.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane prefHeight="400.0" prefWidth="100.0" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.LeftController">
   <children>
      <Button fx:id="button" layoutX="237.0" layoutY="169.0" mnemonicParsing="false" onAction="#buttonClick" text="Button" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" />
   </children>
</AnchorPane>

LeftController.java:

LeftController.java:

package sample;

import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;

import java.awt.event.ActionEvent;
import java.net.URL;
import java.util.ResourceBundle;

public class LeftController implements Initializable {

    @FXML
    private Button button;

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {

    }

    public void buttonClick(javafx.event.ActionEvent actionEvent) {
        System.out.println("Some Stuff");
    }
}

推荐答案

解决方案

您得到的错误是由您的 main(String[]) 方法不是 static 引起的.如果你把它设为 static 那么错误就会消失.

Solution

The error you're getting is caused by your main(String[]) method not being static. If you make it static then the error will go away.

JavaFX 提供了在不提供主方法的情况下启动应用程序的能力,只要主类是Application 的子类.但是,开发人员仍然可以包含一个 main 方法,这意味着这个特殊的启动功能具有优雅地处理这种情况.换句话说,从开发人员的角度来看,Application 子类中存在的显式主方法必须充当应用程序的入口点.尽管如此,在幕后,一些深层次的内部类已经成为真正的"主类.

JavaFX offers the ability to launch applications without providing a main method, so long as the main class is a subclass of Application. However, developers can still include a main method which means this special launch functionality has to handle that situation gracefully. In other words, an explicit main method present in the Application subclass must act like the entry point of the application from the developer's point of view. Nonetheless, behind the scenes some deep internal class has become the "real" main class.

为此,主要方法位于 - 如果存在 - 通过 Class#getMethod(String,Class...) 虽然只返回公共方法,但不区分静态和非静态方法.如果找到,Method#invoke(Object,Object...) 用于反射调用主方法.invoke 的第一个参数是调用方法的实例;在静态方法的情况下,值为 null.不幸的是,代码假定它找到的方法是静态的,这会导致抛出 NullPointerException——你不能在 null 上调用实例方法> 实例".

To do this, the main method is located—if present at all—via Class#getMethod(String,Class...) which, while only returning public methods, doesn't distinguish between static and non-static methods. If found, Method#invoke(Object,Object...) is used to invoke the main method reflectively. The first argument of invoke is the instance that the method should be invoked on; in the case of static methods the value is null. Unfortunately, the code assumes the method it found is static which causes a NullPointerException to be thrown—you can't call an instance method on a null "instance".

更新:此问题已在 GitHub 上提交 (#570)和随后的 JBS(JDK-8230119).当前的想法是发出警告而不是抛出 NullPointerException.但是,允许在没有 main 方法的情况下启动的功能可能会在未来版本中被弃用,这将影响如何解决此问题.

Update: This issue has been submitted on GitHub (#570) and subsequently JBS (JDK-8230119). The current idea is to emit a warning rather than throw the NullPointerException. However, the functionality that allows launching without a main method may be deprecated in a future release, which will affect how this issue is addressed.

这篇关于启动 JavaFX 应用程序时的内部 NPE的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆