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

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

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

Ответ 1

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

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

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

Итак, если вы делаете

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(пакет System).

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

Ответ 2

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

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

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

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

Ответ 3

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

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

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

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

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

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