微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

添加module-info时,为什么Java无法读取相同的资源文件?

如何解决添加module-info时,为什么Java无法读取相同的资源文件?

一个带有标准 Maven 文件夹结构的简单 Java 项目。

src
  main
    java
      mypackage
        Main.java
    resource
      abc
        cde.txt  

Main.java(省略样板)

var path = "abc/cde.txt";
InputStream input = Thread.currentThread().getContextClassLoader().getResourceAsstream(path);

if (input == null) {
    throw new IllegalStateException("Resource not found");
} else {
   // read from input
}

代码工作正常并从绝对路径读取文件
"%project_root%/target/classes/abc/cde.txt"(编译代码)。

添加文件 src/main/java/module-info.java 后,情况发生变化:程序找不到文件并抛出 in branch (input == null)

如何以旧方式从“资源”文件夹中读取文件,并在资源文件夹中同时拥有:java-module 和资源?我想避免在任何地方添加前缀 "src/main/resources"

解决方法

你可能想要这个:

InputStream input = Main.class.getResourceAsStream("/abc/cde.txt");

当您添加 module-info.java 时,Java 会将您的类视为 module

模块具有超出普通旧类路径所具有的封装限制。要访问模块中的资源,其他代码必须通过该模块,该模块将检查调用代码的模块是否有权读取这些资源。

ClassLoader.getResourceAsStream will only read resources from explicitly opened modules:

另外……这个方法只会在包被无条件打开时找到命名模块包中的资源。

但是 Class.getResourceClass.getResourceAsStream 只依赖于类所属的模块,并没有额外的限制。

应该始终使用 Class.getResource 或 Class.getResourceAsStream。应避免使用 ClassLoader 等效项。

Class 方法和 ClassLoader 方法之间有一个重要区别:Class 方法将参数视为相对于类的包,除非参数以斜杠 (/) 开头。

除了封装限制,给定一个名为 com.example.MyApplication 的类,这两行是等价的:

MyApplication.class.getResource("data.txt")
MyApplication.class.getClassLoader().getResource("com/example/data.txt")

这些是等价的:

MyApplication.class.getResource("/data.txt")
MyApplication.class.getClassLoader().getResource("data.txt")

同样,它们仅在资源路径方面等效;模块化封装限制相同。始终使用 Class.getResource* 方法,避免使用 ClassLoader.getResource* 方法。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。