在Java中加载资源的首选方式
我想知道在Java中加载资源的最佳方式:
-
this.getClass().getResource() (or getResourceAsStream())
, -
Thread.currentThread().getContextClassLoader().getResource(name)
, -
System.class.getResource(name)
。
根据你想要的来制定解决scheme…
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)
将使用上下文类加载器加载,但不会根据任何包来parsing名称(它必须被绝对引用)
System.class.getResource(name)
将使用系统类加载器来加载资源(它也必须被绝对引用,因为你不能把任何东西放到java.lang包(System的包)中。
只要看看源代码。 还指出getResourceAsStream只是从getResource返回的URL上调用“openStream”并返回该值。
那么,如果你真的在派生类中,这部分取决于你想要发生什么。
例如,假设SuperClass
在A.jar中, SubClass
在B.jar中,并且你正在SuperClass
声明的一个实例方法中执行代码,但是这里指的是一个SubClass
的实例。 如果使用this.getClass().getResource()
,它将在B.jar中看起来相对于SubClass
。 我怀疑这通常不是什么要求。
就我个人而言,我可能会最经常使用Foo.class.getResourceAsStream(name)
– 如果您已经知道您所使用的资源的名称,并且您确定它与Foo
相关的位置,那么这是最可靠的方法做IMO。
当然,有些时候这也不是你想要的:根据其优点判断每个案例。 这只是“我知道这个资源与这个课程捆绑在一起”是我遇到的最常见的一个。
我search了三个地方,如下所示。 评论欢迎。
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); }
我知道真的很晚了,但我只是想分享最后的帮助。 它也会从文件系统的绝对path(不仅是类path)加载资源/文件。
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; } }
我尝试了很多上面提到的方法和function,但是他们在我的项目中没有工作。 无论如何,我已经find解决办法,这里是:
try { InputStream path = this.getClass().getClassLoader().getResourceAsStream("img/left-hand.png"); img = ImageIO.read(path); } catch (IOException e) { e.printStackTrace(); }