Java加载资源的首选方式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3861989/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 05:58:18  来源:igfitidea点击:

Preferred way of loading resources in Java

javaresources

提问by Doc Davluz

I would like to know the best way of loading a resource in Java:

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

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

采纳答案by Michael Wiles

Work out the solution according to what you want...

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

There are two things that getResource/getResourceAsStream()will get from the class it is called on...

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

  1. The class loader
  2. The starting location
  1. 类加载器
  2. 出发地点

So if you do

所以如果你这样做

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

it will attempt to load foo.txt from the same package as the "this" class and with the class loader of the "this" class. If you put a "/" in front then you are absolutely referencing the resource.

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

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

will load the resource from the class loader of "this" and from the x.y.z package (it will need to be in the same directory as classes in that package).

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

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

will load with the context class loader but will not resolve the name according to any package (it must be absolutely referenced)

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

System.class.getResource(name)

Will load the resource with the system class loader (it would have to be absolutely referenced as well, as you won't be able to put anything into the java.lang package (the package of System).

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

Just take a look at the source. Also indicates that getResourceAsStream just calls "openStream" on the URL returned from getResource and returns that.

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

回答by Jon Skeet

Well, it partly depends what you want to happen if you're actuallyin a derived class.

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

For example, suppose SuperClassis in A.jar and SubClassis in B.jar, and you're executing code in an instance method declared in SuperClassbut where thisrefers to an instance of SubClass. If you use this.getClass().getResource()it will look relative to SubClass, in B.jar. I suspect that's usuallynot what's required.

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

Personally I'd probably use Foo.class.getResourceAsStream(name)most often - if you already know the name of the resource you're after, and you're sure of where it is relative to Foo, that's the most robust way of doing it IMO.

就我个人而言,我可能Foo.class.getResourceAsStream(name)最常使用- 如果您已经知道您所追求的资源的名称,并且您确定它相对于 的位置,那么这是FooIMO 最可靠的方法。

Of course there are times when that's notwhat you want, too: judge each case on its merits. It's just the "I know this resource is bundled with this class" is the most common one I've run into.

当然,有时这也不是您想要的:根据每个案件的优点来判断。只是“我知道此资源与此类捆绑在一起”是我遇到的最常见的问题。

回答by dogbane

I search three places as shown below. Comments welcome.

我搜索三个地方,如下所示。欢迎评论。

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);
}

回答by nyxz

I know it really late for another answer but I just wanted to share what helped me at the end. It will also load resources/files from the absolute path of the file system (not only the classpath's).

我知道另一个答案真的很晚了,但我只是想分享最后对我有帮助的东西。它还将从文件系统的绝对路径(不仅是类路径)加载资源/文件。

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;
    }

}

回答by Vladislav

I tried a lot of ways and functions that suggested above, but they didn't work in my project. Anyway I have found solution and here it is:

我尝试了很多上面建议的方法和功能,但它们在我的项目中不起作用。无论如何,我找到了解决方案,这里是:

try {
    InputStream path = this.getClass().getClassLoader().getResourceAsStream("img/left-hand.png");
    img = ImageIO.read(path);
} catch (IOException e) {
    e.printStackTrace();
}