代码之家  ›  专栏  ›  技术社区  ›  Doc Davluz

Java中加载资源的首选方法

  •  92
  • Doc Davluz  · 技术社区  · 14 年前

    • this.getClass().getResource() (or getResourceAsStream())
    • Thread.currentThread().getContextClassLoader().getResource(name) ,
    • System.class.getResource(name) .
    5 回复  |  直到 14 年前
        1
  •  141
  •   mkobit    8 年前

    根据你想要的解决方案。。。

    有两件事 getResource getResourceAsStream() 将从它被召唤的班级得到。。。

    1. 类加载器
    2. 起始位置

    所以如果你这么做了

    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语言包(系统的包)。

    只要看看来源。还指示getResourceAsStream仅对从getResource返回的URL调用“openStream”,并返回该URL。

        2
  •  14
  •   Jon Skeet    14 年前

    好吧,这在一定程度上取决于如果你是 事实上 在派生类中。

    例如,假设 SuperClass SubClass 在B.jar中,您正在中声明的实例方法中执行代码 this 引用的实例 this.getClass().getResource() 子类 通常 不是要求的。

    我个人可能会用 Foo.class.getResourceAsStream(name) 最常见的情况是,如果您已经知道要查找的资源的名称,并且确定它的相对位置 Foo

    你也想要的是:根据案情判断每个案件。只是“我知道这个资源和这个类捆绑在一起”是我遇到的最常见的一个。

        3
  •  11
  •   dogbane    14 年前

    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);
    }
    
        4
  •  3
  •   nyxz    9 年前

    我知道现在再回答这个问题已经很晚了,但我只是想和大家分享一下最后对我有帮助的东西。它还将从文件系统的绝对路径(不仅仅是类路径)加载资源/文件。

    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;
        }
    
    }
    
        5
  •  0
  •   Vlad    7 年前

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