Почему этот код перестал работать после того, как я переключил машины?
Я работал над проектом на Java с использованием Eclipse, который требует загрузки некоторых изображений и их отображения. Сначала я загрузил их так:
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. Но недавно я получил новый ноутбук, и когда я попытался запустить его на новой машине, банка не работала; 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) и другие настройки, что и старый, но вместо Oxygen работает Eclipse Photon.
Итак, в чем разница между двумя способами загрузки ресурсов? (Я слышал, что это что-то о ClassLoaders, но я не могу вспомнить точные слова.) Почему переключение на новую машину сломало первую? И даже со вторым, я делаю это правильно?
1 ответ
MyClass.class возвращает экземпляр java.lang.Class, представляющий класс MyClass
, Вызов.getClass для этого возвращает экземпляр класса, представляющий java.lang.Class
сам и зовет getResourceAsStream
на это будет пытаться найти ресурс в java.base (где java.lang.Class
жизни). В общем, не то, что вы хотите. Другими словами, ваш первый пример такой же, как java.lang.Class.class.getResourceAsStream(...)
,
Второй пример - правильный способ сделать это.
Причина, по которой первая вещь работает в нескольких местах, заключается в том, что все зависит от того, как был указан Class.getResourceXXX в Java SE 8 и более ранних версиях. Спецификация изменена в Java SE 9 для работы с классами, где Class является именованным модулем.