getClass().getResource() 抛出 NullPointerException [duplicate]

getClass().getResource() throws a NullPointerException [duplicate]

提问人:DIEGO IGLESIAS 提问时间:6/9/2022 最后编辑:DIEGO IGLESIAS 更新时间:6/9/2022 访问量:449

问:

我目前正在尝试使用 IntelliJ 和 JavaFX 开始编写应用程序,我有以下代码:

package main.gui;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.net.URL;

public class MainMenu extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("hello-view.fxml"));
        URL url = getClass().getResource("hello-view.fxml");
        System.out.println("URL = " + url);
        Parent root = FXMLLoader.load(url);
        Scene scene = new Scene(root,1920,1080);
        stage.setTitle("Hello!");
        stage.setScene(scene);
        stage.show();
    }

}

我的文件结构:

  • src/main/gui/MainMenu.java
  • src/main/gui/hello-view.fxml

我得到这个例外:

Exception in Application start method
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:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1082)
Caused by: java.lang.RuntimeException: Exception in Application start method
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:901)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:196)
    at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.NullPointerException: Location is required.
    at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3324)
    at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3287)
    at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3255)
    at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3227)
    at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3203)
    at javafx.fxml/javafx.fxml.FXMLLoader.load(FXMLLoader.java:3196)
    at main/main.gui.MainMenu.start(MainMenu.java:13)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:847)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:484)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:457)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:456)
    at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:184)
    ... 1 more

它输出:URL = null

我尝试了很多我在这个网站上找到的东西,但没有成功......

提前感谢您的帮助:)

java javafx nullpointerexception fxml

评论

3赞 Slaw 6/9/2022
@MatteoNNZ 这只是 Maven 和 Gradle 等使用的约定。OP 没有提到使用任何一个构建工具,只提到使用 IntelliJ。在他们的情况下,似乎是一个带有“源根”的mainsrc
2赞 Slaw 6/9/2022
@MatteoNNZ 另外,为什么要坚持使用 OP 而不是?后者也同样有效;另外,在 OP 的情况下,他们可以使用相对资源名称(而不是绝对名称,尽管我更喜欢使用绝对名称)。一个很好的好处是,后者将更好地与JPMS世界配合使用(如果你的代码是模块化的),特别是当从与类相同的模块中加载资源时(即,不需要无条件地使用资源包)。ClassLoader#getResource(String)Class#getResource(String)opens
3赞 Slaw 6/9/2022
@MatteoNNZ 是的,我已经看到这样的变化也解决了这个问题。但是,无论使用 or ,只要传入的参数对于给定的 API 是正确的(尤其是对于非模块化代码),它就真的无关紧要。我之所以发表评论,是因为我觉得很奇怪,人们经常建议改用前者,而不仅仅是解决后者的使用:)。我对这个建议的问题是 OP 的代码似乎在不使用 .虽然他们有,所以也许事情搞砸了。ClassLoader#getResource(String)Class#getResource(String)src/main/resourcessrc/main/javasrc/main
1赞 Slaw 6/9/2022
@DIEGOIGLESIAS 请添加有关您的环境和项目结构的信息。我无法从我对您如何设置项目的猜测中重现您的问题。您是如何在 IntelliJ 中创建项目的?您使用的是 Gradle 吗?Maven?也不?如果您使用的是构建工具,您如何执行项目?通过构建工具,还是通过 IntelliJ 自己的构建系统?一个最小的可重复的例子是最好的。看看如何确定 FXML 文件、CSS 文件、图像和 JavaFX 应用程序所需的其他资源的正确路径是否有帮助。
4赞 rzwitserloot 6/9/2022
另外,是双重错误的。[A] 不要使用(这是毫无意义的类型化,它删除了相对于类型去的能力,如果你想去相对于 root,只需调用一个类并在前面插一个斜杠,在特殊情况下可以返回 null,而 [B] 使用,而不是 - 在某些条件下子类化时中断。getClass().getClassLoader().getResource().getClassLoader().getResource.getClassLoader()MyClass.classgetClass()getClass()

答:

0赞 DIEGO IGLESIAS 6/9/2022 #1

添加更多细节:我正在使用 Maven,我使用 随 IntelliJ 提供的 JavaFX 项目创建工具。

我按照@MatteoNNZ的建议,简单地将我的fxml文件放入ressources文件夹(src/main/resources)中,使它工作。 我稍微调整了一下代码,使其具有以下内容:

package main.gui;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.net.URL;

public class MainMenu extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        URL url = getClass().getClassLoader().getResource("hello-view.fxml");
        System.out.println("URL = " + url);
        Parent root = FXMLLoader.load(url);
        Scene scene = new Scene(root,1920,1080);
        stage.setTitle("Hello!");
        stage.setScene(scene);
        stage.show();
    }

}

显然,它可以像这样简化:

@Override
    public void start(Stage stage) throws Exception {
//        URL url = getClass().getClassLoader().getResource("hello-view.fxml"); |
//        System.out.println("URL = " + url);                                   | Remove these 3 lines
//        Parent root = FXMLLoader.load(url);                                   |
        Scene scene = new Scene(FXMLLoader.load(getClass().getClassLoader().getResource("hello-view.fxml")),1920,1080);
        stage.setTitle("Hello!");
        stage.setScene(scene);
        stage.show();
    }

但它非常丑陋。

谢谢大家的帮助和非常快速的回答:)。

评论

4赞 Slaw 6/9/2022
请注意,如果您使用的是 Maven,那么您的源文件(即文件)都应该在目录下。下面的任何目录都是包。您可能也想解决此问题。*.javasrc/main/javasrc/main/java
0赞 Matteo NNZ 6/9/2022
事实上,正如@Slaw提到的,如果你使用的是 IntelliJ 项目向导(我确信这一点),你应该坚持使用他们建议的结构,Java 下的源文件(因此它们成为包)和资源下的资源文件
1赞 jewelsea 6/10/2022
有关基于 Maven 的项目的项目结构的更多信息,请参见 baeldung 中也介绍了标准目录布局,以更好地了解您的构建工具学习 maven 入门和 maven 基础知识以及在 ide 中使用 maven