【问题标题】:Why did this code stop working after I switched machines?为什么我切换机器后这段代码停止工作?
【发布时间】:2019-02-15 11:44:35
【问题描述】:

我使用 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 内部运行时,不会出现此问题。

最后,经过一番实验,我把代码改成了直接在MyClass.class上调用getResourceAsStream()而不调用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 的东西,但我不记得确切的词了。)为什么切换到新机器会破坏第一个机器?即使是第二个,我做得对吗?

【问题讨论】:

    标签: java jar resources classloader resource-loading


    【解决方案1】:

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

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

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

    【讨论】:

      猜你喜欢
      • 2013-10-05
      • 2018-08-03
      • 1970-01-01
      • 1970-01-01
      • 2021-07-30
      • 2020-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多