Я хотел бы узнать лучший способ загрузки ресурса в 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". Если вы положили "/" спереди, вы абсолютно ссылаетесь на ресурс.
this.getClass().getResource("/x/y/z/foo.txt")
загрузит ресурс из загрузчика классов "this" и из пакета x.y.z(он должен быть в том же каталоге, что и классы в этом пакете).
Thread.currentThread().getContextClassLoader().getResource(name)
будет загружаться с помощью загрузчика класса контекста, но не будет разрешать имя в соответствии с любым пакетом (он должен быть абсолютно привязан)
System.class.getResource(name)
Будет загружен ресурс загрузчиком системного класса (он также должен быть абсолютно привязан, так как вы не сможете вставить что-либо в пакет java.lang(пакет System).
Просто взгляните на источник. Также указывает, что getResourceAsStream просто вызывает "openStream" по URL-адресу, возвращенному из getResource, и возвращает это.
Ну, это отчасти зависит от того, что вы хотите, если вы действительно находитесь в производном классе.
Например, предположим, что SuperClass
находится в A.jar и SubClass
находится в B.jar, и вы выполняете код в методе экземпляра, объявленном в SuperClass
, но где this
ссылается на экземпляр SubClass
. Если вы используете this.getClass().getResource()
, он будет выглядеть относительно SubClass
, в B.jar. Я подозреваю, что обычно это не то, что нужно.
Лично я, вероятно, чаще всего использовал бы Foo.class.getResourceAsStream(name)
- если вы уже знаете имя ресурса, за которым вы находитесь, и вы уверены, где он относится к Foo
, то самый надежный способ это ИМО.
Конечно, бывают случаи, когда это не то, что вы хотите, тоже: судите о каждом случае по существу. Это просто "Я знаю, что этот ресурс связан с этим классом" является наиболее распространенным, с которым я столкнулся.
Я ищу три места, как показано ниже. Комментарии приветствуются.
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 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();
}