我使用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。
那么,两种加载资源的方式有什么区别? (我听说这与ClassLoader有关,但是我记不清确切的词了。)为什么切换到新机器会破坏第一台机器?而且即使是第二个,我也能正确执行吗?
答案 0 :(得分:2)
MyClass.class返回代表类MyClass
的java.lang.Class实例。调用.getClass会返回代表java.lang.Class
本身的Class实例,并在THAT上调用getResourceAsStream
会尝试在java.base(java.lang.Class
所在的位置)中找到资源。通常,不是您想要的。换句话说,您的第一个示例与java.lang.Class.class.getResourceAsStream(...)
相同。
第二个示例是正确的方法。
第一件事在某些地方起作用的原因在于,这完全取决于Java SE 8和更早版本中Class.getResourceXXX的指定方式。 Java SE 9中对规范进行了更改,以处理其中Class是命名模块的类。