Я хотел бы узнать, как лучше всего загрузить ресурс на Java:
this.getClass().getResource() (or getResourceAsStream())
,Thread.currentThread().getContextClassLoader().getResource(name)
,System.class.getResource(name)
.
Я хотел бы узнать, как лучше всего загрузить ресурс на Java:
this.getClass().getResource() (or getResourceAsStream())
,Thread.currentThread().getContextClassLoader().getResource(name)
,System.class.getResource(name)
.Ответы:
Разработайте решение в соответствии с тем, что вы хотите ...
Есть две вещи, которые getResource
/ getResourceAsStream()
получит от класса, для которого он вызван ...
Итак, если вы это сделаете
this.getClass().getResource("foo.txt");
он попытается загрузить файл foo.txt из того же пакета, что и класс this, и с помощью загрузчика классов этого класса. Если вы поставите перед ним «/», то вы полностью ссылаетесь на ресурс.
this.getClass().getResource("/x/y/z/foo.txt")
загрузит ресурс из загрузчика классов «this» и из пакета xyz (он должен находиться в том же каталоге, что и классы в этом пакете).
Thread.currentThread().getContextClassLoader().getResource(name)
загрузится с помощью загрузчика класса контекста, но не разрешит имя в соответствии с каким-либо пакетом (на него должна быть абсолютная ссылка)
System.class.getResource(name)
Загрузит ресурс с помощью загрузчика системного класса (на него также должна быть абсолютная ссылка, так как вы не сможете ничего поместить в пакет java.lang (пакет System).
Просто взгляните на источник. Также указывает, что getResourceAsStream просто вызывает «openStream» для URL, возвращенного из getResource, и возвращает его.
Thread#setContextClassLoader
. Это полезно, если вам нужно изменить путь к классам во время выполнения программы.
Что ж, отчасти это зависит от того, что вы хотите, если вы на самом деле находитесь в производном классе.
Например, предположим, что он SuperClass
находится в A.jar и SubClass
находится в B.jar, и вы выполняете код в методе экземпляра, объявленном в, SuperClass
но где this
ссылается на экземпляр SubClass
. Если вы this.getClass().getResource()
его используете, он будет выглядеть относительно SubClass
, в B.jar. Я подозреваю, что обычно этого не требуется.
Лично я, вероятно, использовал бы Foo.class.getResourceAsStream(name)
чаще всего - если вы уже знаете имя ресурса, который вам нужен, и вы уверены, где оно относительно Foo
, это самый надежный способ сделать это, ИМО.
Конечно, бывают случаи, когда вы тоже этого не хотите: судите каждое дело по существу. Просто «Я знаю, что этот ресурс связан с этим классом» - самый распространенный вопрос, с которым я сталкивался.
this.getClass()
. Создайте экземпляр подкласса и вызовите метод ... он распечатает имя подкласса, а не суперкласса.
Я ищу в трех местах, как показано ниже. Комментарии приветствуются.
public URL getResource(String resource){
URL url ;
//Try with the Thread Context Loader.
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if(classLoader != null){
url = classLoader.getResource(resource);
if(url != null){
return url;
}
}
//Let's now try with the classloader that loaded this class.
classLoader = Loader.class.getClassLoader();
if(classLoader != null){
url = classLoader.getResource(resource);
if(url != null){
return url;
}
}
//Last ditch attempt. Get the resource from the classpath.
return ClassLoader.getSystemResource(resource);
}
Я знаю, что уже поздно для другого ответа, но я просто хотел поделиться тем, что помогло мне в конце. Он также будет загружать ресурсы / файлы из абсолютного пути файловой системы (а не только из пути к классам).
public class ResourceLoader {
public static URL getResource(String resource) {
final List<ClassLoader> classLoaders = new ArrayList<ClassLoader>();
classLoaders.add(Thread.currentThread().getContextClassLoader());
classLoaders.add(ResourceLoader.class.getClassLoader());
for (ClassLoader classLoader : classLoaders) {
final URL url = getResourceWith(classLoader, resource);
if (url != null) {
return url;
}
}
final URL systemResource = ClassLoader.getSystemResource(resource);
if (systemResource != null) {
return systemResource;
} else {
try {
return new File(resource).toURI().toURL();
} catch (MalformedURLException e) {
return null;
}
}
}
private static URL getResourceWith(ClassLoader classLoader, String resource) {
if (classLoader != null) {
return classLoader.getResource(resource);
}
return null;
}
}
Я пробовал много способов и функций, которые предлагались выше, но они не работали в моем проекте. В любом случае я нашел решение, и вот оно:
try {
InputStream path = this.getClass().getClassLoader().getResourceAsStream("img/left-hand.png");
img = ImageIO.read(path);
} catch (IOException e) {
e.printStackTrace();
}
this.getClass().getResourceAsStream()
в этом случае. Если вы посмотрите на источник getResourceAsStream
метода, вы заметите, что он делает то же самое, что и вы, но более разумным способом (откат, если его нет, ClassLoader
можно найти в классе). Это также указывает на то, что вы можете столкнуться с потенциалом null
на getClassLoader
в вашем коде ...
this.getClass().getResourceAsStream()
, у меня не работает, поэтому я использую это работает. Я думаю, что есть люди, которые могут столкнуться с такой проблемой, как моя.