启动JavaFX应用程序时使用内部NPE [英] Internal NPE when launching JavaFX Application
问题描述
因此,基本上,我开始了一个虚拟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选项设置为:-模块路径"C:\ Program Files \ Java \ javafx-sdk-11.0.2 \ lib" --add-modules javafx.controls,javafx.fxml
I am using IntelliJ. JavaFX libraries are set correctly and VM Options set to:
--module-path "C:\Program Files\Java\javafx-sdk-11.0.2\lib" --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:
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" />
MainWindowController:
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;
}
}
Left.fxml:
Left.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.
只要主类是 Application
的子类,JavaFX便可以在不提供main方法的情况下启动应用程序.但是,开发人员仍可以包括main方法,这意味着特殊启动功能具有优雅地处理这种情况.换句话说,从开发者的角度来看,存在于 Application
子类中的显式main方法必须像应用程序的入口点一样工作.尽管如此,在幕后,一些深层的内部阶级已经成为真正的"主要阶级.
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.
为此,通过 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上提交( JDK-8230119 ).当前的想法是发出警告,而不是抛出 NullPointerException
.但是,在将来的发行版中可能会弃用允许不使用主要方法启动的功能,这将影响解决此问题的方式.
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屋!