Предпочтительный способ загрузки ресурсов в Java - PullRequest
98 голосов
/ 05 октября 2010

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

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

Ответы [ 5 ]

129 голосов
/ 05 октября 2010

Разрабатывайте решение в соответствии с вашими желаниями ...

Есть две вещи, которые getResource / getResourceAsStream() получат от класса, для которого он вызывается ...

  1. Загрузчик классов
  2. Начальное местоположение

Так что если вы сделаете

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

, он попытается загрузить foo.txt из того же пакетакак класс "this" и с загрузчиком классов класса "this".Если вы ставите «/» впереди, то вы абсолютно ссылаетесь на ресурс.

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

загрузит ресурс из загрузчика классов «this» и из пакета xyz (он должен быть втот же каталог, что и классы в этом пакете).

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

будет загружаться с загрузчиком классов контекста, но не будет разрешать имя в соответствии с каким-либо пакетом (на него должна быть абсолютная ссылка)

System.class.getResource(name)

Загрузит ресурс с помощью загрузчика системного класса (на него также нужно будет ссылаться абсолютно, так как вы не сможете ничего поместить в пакет java.lang (пакет System).

Просто посмотрите на источник. Также указывает, что getResourceAsStream просто вызывает «openStream» для URL-адреса, возвращенного из getResource, и возвращает его.

13 голосов
/ 05 октября 2010

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

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

Лично я бы, вероятно, использовал Foo.class.getResourceAsStream(name) чаще всего - если вы уже знаете название ресурса, к которому вы обращаетесь, и уверены, где он находится относительно Foo, это самый надежный способ делает это ИМО.

Конечно, бывают случаи, когда это не , что вы тоже хотите: судите каждое дело по существу. Просто «Я знаю, что этот ресурс связан с этим классом», это самый распространенный, с которым я столкнулся.

9 голосов
/ 05 октября 2010

Я ищу три места, как показано ниже.Комментарии приветствуются.

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);
}
3 голосов
/ 29 января 2016

Я знаю, что уже поздно для другого ответа, но я просто хотел поделиться тем, что помогло мне в конце. Он также будет загружать ресурсы / файлы из абсолютного пути файловой системы (не только пути к классам).

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

}
0 голосов
/ 24 мая 2017

Я перепробовал много способов и функций, которые предлагались выше, но они не работали в моем проекте. В любом случае, я нашел решение, и вот оно:

try {
    InputStream path = this.getClass().getClassLoader().getResourceAsStream("img/left-hand.png");
    img = ImageIO.read(path);
} catch (IOException e) {
    e.printStackTrace();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...