为什么这台代码在我切换机器后停止工作?

时间:2021-08-24 02:54:21

I have worked on a project in Java using Eclipse that requires loading some images and displaying them. At first, I loaded them this way:

我使用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);

And this worked fine, whether I'm running it from Eclipse or from an executable jar. But I recently got a new laptop, and when I tried to run it on the new machine, the jar would not run; stream always turns out to be null. However, this problem does not occur when I'm running from inside Eclipse.

无论我是从Eclipse运行还是从可执行jar运行它,这都很好。但是我最近买了一台新笔记本电脑,当我试图在新机器上运行它时,罐子就不会运行了;流总是变成null。但是,当我从Eclipse内部运行时,不会发生此问题。

Finally, after some experimentation, I changed the code to call getResourceAsStream() directly on MyClass.class without calling getClass():

最后,经过一些实验,我更改了代码,直接在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);

And for some reason, it works. My new laptop has the same OS (Windows 10) and other settings as the old one, but it runs Eclipse Photon instead of Oxygen.

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

So, what is the difference between the two ways of loading resources? (I've heard that it's something about ClassLoaders, but I cannot remember the exact words.) Why did switching to a new machine break the first one? And even with the second one, am I doing it correctly?

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

1 个解决方案

#1


2  

MyClass.class returns the java.lang.Class instance representing the class MyClass. Calling .getClass on that returns the Class instance representing java.lang.Class itself, and calling getResourceAsStream on THAT will attempt to locate the resource in java.base (where java.lang.Class lives). Generally, not what you want. In other words, your first example is the same as java.lang.Class.class.getResourceAsStream(...).

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

The second example is the proper way to do it.

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

The reason the first thing does work in a few places is because it's up to exactly how Class.getResourceXXX was specified in Java SE 8 and older. The specification changed in Java SE 9 to deal with classes where the Class is a named module.

第一件事在一些地方工作的原因是因为它完全取决于如何在Java SE 8及更早版本中指定Class.getResourceXXX。 Java SE 9中的规范已更改,以处理Class是命名模块的类。

#1


2  

MyClass.class returns the java.lang.Class instance representing the class MyClass. Calling .getClass on that returns the Class instance representing java.lang.Class itself, and calling getResourceAsStream on THAT will attempt to locate the resource in java.base (where java.lang.Class lives). Generally, not what you want. In other words, your first example is the same as java.lang.Class.class.getResourceAsStream(...).

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

The second example is the proper way to do it.

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

The reason the first thing does work in a few places is because it's up to exactly how Class.getResourceXXX was specified in Java SE 8 and older. The specification changed in Java SE 9 to deal with classes where the Class is a named module.

第一件事在一些地方工作的原因是因为它完全取决于如何在Java SE 8及更早版本中指定Class.getResourceXXX。 Java SE 9中的规范已更改,以处理Class是命名模块的类。