繁体   English   中英

Java加载资源的首选方式

[英]Preferred way of loading resources in Java

我想知道在 Java 中加载资源的最佳方式:

  • this.getClass().getResource() (or getResourceAsStream())
  • Thread.currentThread().getContextClassLoader().getResource(name) ,
  • System.class.getResource(name)

根据您的需要制定解决方案...

getResource / getResourceAsStream()将从它被调用的类中获得两件事......

  1. 类加载器
  2. 出发地点

所以如果你这样做

this.getClass().getResource("foo.txt");

它将尝试从与“this”类相同的包中加载 foo.txt,并使用“this”类的类加载器。 如果您在前面放了一个“/”,那么您绝对是在引用资源。

this.getClass().getResource("/x/y/z/foo.txt")

将从“this”的类加载器和 xyz 包中加载资源(它需要与该包中的类位于同一目录中)。

Thread.currentThread().getContextClassLoader().getResource(name)

将使用上下文类加载器加载,但不会根据任何包解析名称(必须绝对引用)

System.class.getResource(name)

将使用系统类加载器加载资源(它也必须被绝对引用,因为您将无法将任何内容放入 java.lang 包(系统包)。

只需看一下来源。 还表示 getResourceAsStream 只是在从 getResource 返回的 URL 上调用“openStream”并返回它。

好吧,如果您实际上在派生类中,这部分取决于您想要发生什么。

例如,假设SuperClass在 A.jar 中,而SubClass在 B.jar 中,并且您正在SuperClass声明的实例方法中执行代码,但是this指的是SubClass的实例。 如果您使用this.getClass().getResource()它将看起来相对于 B.jar 中的SubClass 我怀疑这通常不是必需的。

就我个人而言,我可能最常使用Foo.class.getResourceAsStream(name) - 如果您已经知道您要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'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();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM