【问题标题】:Subdirectory classloading fails with modular JavaFX模块化 JavaFX 导致子目录类加载失败
【发布时间】:2020-07-06 15:34:33
【问题描述】:

我制作了一个 Gradle 项目,它使用类加载器从子目录资源/文本中加载文本文件。此时它可以工作,但是当我将项目转换为模块化 JavaFX 程序时,相同的类加载器函数会给出 NullPointerException。

src/主项目目录

└───src
    └───main
        ├───java
        │   │   module-info.java
        │   └───app
        │           Main.java
        └───resources
            └───text
                    words.txt

build.gradle

plugins {
    id 'application'
    id 'org.openjfx.javafxplugin' version '0.0.8'
}

sourceCompatibility = 11

repositories {
    jcenter()
}

javafx {
    version = '13.0.1'
    modules = [ 'javafx.controls']
}

mainClassName = 'exMod/app.Main'
jar {
    manifest {
        attributes 'Main-Class': mainClassName
    }
}

模块信息.java

module exMod {
    requires javafx.controls;
    exports app;
}

Main.java

package app;

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class Main extends Application {

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

    public void start(Stage stage){
        stage.setTitle("Hello World!");
        Button button = new Button();
        Label label = new Label();
        button.setText("Click me!");
        button.setOnAction(event -> label.setText(getWords()));

        VBox root = new VBox();
        root.setAlignment(Pos.CENTER);
        root.getChildren().addAll(button, label);
        stage.setScene(new Scene(root, 300, 250));
        stage.show();
    }

    private String getWords(){
        String path = "text/words.txt";
        InputStream inputStream = getClass().getClassLoader().getResourceAsStream(path);
        InputStreamReader isReader = new InputStreamReader(inputStream); // null exception
        BufferedReader reader = new BufferedReader(isReader);
        StringBuilder content = new StringBuilder();
        try {
            String line;
            while( (line = reader.readLine()) != null) {
                content.append(line);
            }
        } catch(IOException e){
                e.printStackTrace();
        }
        return content.toString();
    }
}

如果我将路径变量更改为“words.txt”并将文本文件上移一级到 src/main/resources,它可以工作,但由于某种原因我无法发现,从资源子目录将不起作用。是什么导致 NullPointerException,我该如何解决?

【问题讨论】:

  • 我认为包含在我的问题中不够重要,所以我将在此处说明:我的 words.txt 文件仅包含这句话“红狐跳过懒狗。”

标签: java gradle javafx java-module resource-files


【解决方案1】:

用户 Holger 在对this question 的评论中,作为program.class.getClassLoader().getResource("b/text.txt") 的替代选择

...你应该使用program.class.getResource("b/text.txt"), 解析相对于程序类位置的资源。 否则,一旦您使用模块,它可能会在 Java 9 或更高版本中失败,因为 上到类加载器会破坏关于 实际模块。

因此,我尝试仅使用 getClass().getResourceAsStream(path) 而不是 getClass().getClassLoader().getResourceAsStream(path)

我还阅读了 Alan Bateman 对 this question 的评论,他说

资源被封装了,所以无法用 ClassLoader 找到 蜜蜂。我假设 ComboBoxStyling.class..getResource("/css/styleclass.css") 将工作 - 注意前导斜杠,以便找到相对于根的斜杠 模块的位置,与此中的 ComboBoxStyling.class 无关 案例。

所以我碰巧一起尝试了这个组合,它奏效了!

getWords()

private String getWords(){
        String path = "/text/words.txt";
        InputStream in = getClass().getResourceAsStream(path);
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        StringBuilder content = new StringBuilder();
        try {
            String line;
            while( (line = reader.readLine()) != null) {
                content.append(line);
            }
        } catch(IOException e){
                e.printStackTrace();
        }
        return content.toString();
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-29
    • 2017-04-23
    • 1970-01-01
    • 1970-01-01
    • 2018-04-11
    • 1970-01-01
    • 2013-08-03
    • 2013-03-25
    相关资源
    最近更新 更多