我想知道用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)
。Answers:
根据您的需要制定解决方案...
从被调用的类中getResource
/ getResourceAsStream()
将获得两件事...
所以如果你这样做
this.getClass().getResource("foo.txt");
它将尝试从与“ this”类相同的包中以及“ this”类的类加载器中加载foo.txt。如果在前面加上“ /”,则绝对是在引用资源。
this.getClass().getResource("/x/y/z/foo.txt")
将从“ this”的类加载器和xyz包中加载资源(它必须与该包中的类位于同一目录中)。
Thread.currentThread().getContextClassLoader().getResource(name)
将使用上下文类加载器加载,但不会根据任何包解析名称(必须绝对引用)
System.class.getResource(name)
将使用系统类加载器加载资源(也必须绝对引用该资源,因为您将无法在java.lang包(System的包)中放入任何内容。
只需查看源代码即可。还指示getResourceAsStream只是在从getResource返回的URL上调用“ openStream”并将其返回。
Thread#setContextClassLoader
。如果您需要在程序执行时修改类路径,这将很有用。
好吧,这部分取决于如果您实际上在派生类中会发生什么。
例如,假设SuperClass
在A.jar和SubClass
B.jar中,并且您正在中声明的实例方法中执行代码,SuperClass
但其中this
引用的实例SubClass
。如果使用this.getClass().getResource()
它,它将相对于SubClass
B.jar中的。我怀疑通常不是必需的。
我个人可能会Foo.class.getResourceAsStream(name)
最常使用-如果您已经知道要使用的资源的名称,并且确定该资源相对于的位置Foo
,那将是执行IMO的最可靠的方法。
当然,有时候也不是您想要的:根据每个案例的优劣来判断。只是“我知道此资源与此类捆绑在一起”是我遇到的最常见的资源。
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()
对我不起作用,因此我使用了它。我认为有些人可以面对像我这样的问题。