Предпочтительный способ загрузки ресурсов в Java


Я хотел бы знать, лучший способ загрузки ресурса в Java:

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

5 ответов:

разработайте решение в соответствии с тем, что вы хотите...

есть две вещи, которые 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 просто вызывает "openStream" по URL-адресу, возвращенному из getResource, и возвращает его.

Ну, это отчасти зависит от того, что вы хотите произойти, если вы на самом деле в производном классе.

например,SuperClass находится внутри A.jar и SubClass находится внутри B.jar, и вы выполняете код в методе экземпляра, объявленном в SuperClass а, где this относится к экземпляру SubClass. Если вы используете this.getClass().getResource() это будет выглядеть по отношению к SubClass, in B.jar. Я подозреваю, что это обычно не то, что требуется.

лично я бы, наверное, использовать 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();
}