1

我使用 Eclipse 在 Java 中进行了一个项目,该项目需要加载一些图像并显示它们。起初,我以这种方式加载它们:

InputStream stream = MyClass.class.getClass().getResourceAsStream("/resources/ui/icons/" + name);
Image img = ImageIO.read(stream).getScaledInstance(size.width, size.height, Image.SCALE_SMOOTH);

这很好用,无论我是从 Eclipse 还是从可执行 jar 运行它。但是我最近买了一台新笔记本电脑,当我尝试在新机器上运行它时,jar 无法运行;stream事实证明总是如此null。但是,当我从 Eclipse 内部运行时,不会出现此问题。

最后,经过一些实验,我将代码更改为getResourceAsStream()直接MyClass.class调用而不调用getClass()

InputStream stream = MyClass.class.getResourceAsStream("/resources/ui/icons/" + name);
Image img = ImageIO.read(stream).getScaledInstance(size.width, size.height, Image.SCALE_SMOOTH);

由于某种原因,它有效。我的新笔记本电脑具有与旧笔记本电脑相同的操作系统(Windows 10)和其他设置,但它运行的是 Eclipse Photon 而不是 Oxygen。

那么,这两种加载资源的方式有什么区别呢?(我听说这是关于 ClassLoaders 的事情,但我不记得确切的词了。)为什么切换到新机器会破坏第一个机器?即使是第二个,我做得对吗?

4

1 回答 1

2

MyClass.class 返回代表类的 java.lang.Class 实例MyClass。调用 .getClass 返回代表java.lang.Class自身的 Class 实例,调用getResourceAsStreamTHAT 将尝试定位 java.base 中的资源(所在的位置java.lang.Class)。一般来说,不是你想要的。换句话说,您的第一个示例与java.lang.Class.class.getResourceAsStream(...).

第二个例子是正确的方法。

第一件事情在一些地方起作用的原因是因为它完全取决于 Java SE 8 和更早版本中 Class.getResourceXXX 的指定方式。Java SE 9 中的规范进行了更改,以处理 Class 是命名模块的类。

于 2018-09-11T02:45:57.370 回答