Вопрос-ответ

What is the difference between Class.getResource() and ClassLoader.getResource()?

В чем разница между Class.getResource() и ClassLoader.getResource()?

Интересно, в чем разница между Class.getResource() и ClassLoader.getResource()?

редактировать: я особенно хочу знать, задействовано ли какое-либо кэширование на уровне файла / каталога. Как в "кэшируются ли списки каталогов в версии класса?"

AFAIK, следующее должно по сути делать то же самое, но это не так:

getClass().getResource() 
getClass().getClassLoader().getResource()

Я обнаружил это, когда работал с некоторым кодом генерации отчетов, который создает новый файл в WEB-INF/classes/ из существующего файла в этом каталоге. При использовании метода из Class я смог найти файлы, которые были там при развертывании, используя getClass().getResource(), но при попытке извлечь вновь созданный файл я получил нулевой объект. Просмотр каталога ясно показывает, что там находится новый файл. Имена файлов были предварены косой чертой, как в "/myFile.txt".

С другой стороны, ClassLoader версия getResource() действительно обнаружила сгенерированный файл. Исходя из этого опыта, кажется, что происходит какое-то кэширование списка каталогов. Прав ли я, и если да, то где это задокументировано?

Из документации API по Class.getResource()


Находит ресурс с заданным именем. Правила поиска ресурсов, связанных с данным классом, реализуются определяющим загрузчиком класса класса. Этот метод делегируется загрузчику класса этого объекта. Если этот объект был загружен загрузчиком классов bootstrap, метод делегирует ClassLoader.getSystemResource(java.lang.Строка).


Для меня это означает "Class.getResource действительно вызывает getResource() своего собственного ClassLoader". Что было бы то же самое, что делать getClass().getClassLoader().getResource(). Но это, очевидно, не так. Не мог бы кто-нибудь, пожалуйста, просветить меня по этому вопросу?

Переведено автоматически
Ответ 1

Class.getResource может принимать "относительное" имя ресурса, которое обрабатывается относительно пакета класса. В качестве альтернативы вы можете указать "абсолютное" имя ресурса, используя начальную косую черту. Пути к ресурсам Classloader всегда считаются абсолютными.

Итак, следующее в основном эквивалентно:

foo.bar.Baz.class.getResource("xyz.txt");
foo.bar.Baz.class.getClassLoader().getResource("foo/bar/xyz.txt");

И эти тоже (но они отличаются от приведенных выше):

foo.bar.Baz.class.getResource("/data/xyz.txt");
foo.bar.Baz.class.getClassLoader().getResource("data/xyz.txt");
Ответ 2

Первый вызов выполняет поиск относительно .class файла, в то время как второй выполняет поиск относительно корневого пути к классу.

Для отладки подобных проблем я печатаю URL:

System.out.println( getClass().getResource(getClass().getSimpleName() + ".class") );
Ответ 3

Пришлось поискать это в спецификациях:

getResource() класса - документация указывает на разницу:


Этот метод делегирует вызов своему загрузчику классов после внесения этих изменений в имя ресурса: если имя ресурса начинается с "/", оно остается неизменным; в противном случае имя пакета добавляется к имени ресурса после преобразования "." в "/". Если этот объект был загружен загрузчиком bootstrap, вызов делегируется ClassLoader.getSystemResource.


Ответ 4

Все эти ответы здесь, а также ответы в этом вопросе, предполагают, что загрузка абсолютных URL-адресов, таких как "/ foo /bar.properties", обрабатывается одинаково с помощью class.getResourceAsStream(String) и class.getClassLoader().getResourceAsStream(String). Это НЕ тот случай, по крайней мере, не в моей конфигурации / версии Tomcat (в настоящее время 7.0.40).

MyClass.class.getResourceAsStream("/foo/bar.properties"); // works!  
MyClass.class.getClassLoader().getResourceAsStream("/foo/bar.properties"); // does NOT work!

Извините, у меня нет абсолютно удовлетворительного объяснения, но я предполагаю, что tomcat проделывает грязные трюки и свою черную магию с загрузчиками классов и вызывает разницу. Я всегда использовал class.getResourceAsStream(String) в прошлом и у меня не было никаких проблем.

PS: Я также разместил это здесь

java