Difference Between Class.getResource() and ClassLoader.getResource() – Class.getResource()和ClassLoader.getResource()的区别

最后修改: 2022年 9月 16日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this short tutorial, we’ll look at the differences between the Class.getResource() and ClassLoader.getResource() methods.

在这个简短的教程中,我们将看看Class.getResource()ClassLoader.getResource()方法之间的区别。

2. The getResource() Method

2.getResource()方法

We can use the getResource() method on either a Class or ClassLoader instance to find a resource with the given name. The resource is considered to be data — for instance, images, text, audio, and so on. As a path separator, we should always use a slash (“/”).

我们可以在ClassClassLoader实例上使用getResource()方法来查找具有给定名称的资源。资源被认为是数据–例如,图片、文本、音频等等。作为路径分隔符,我们应该总是使用斜线(”/”)。

The method returns a URL object for reading the resource, or the null value if the resource cannot be found or the invoker doesn’t have privileges to retrieve the resource.

该方法返回一个用于读取资源的URL对象,如果找不到资源或调用者没有检索资源的权限,则返回null值。

3. Class.getResource()

3.Class.getResource()

Now, let’s see how we can get the resource using a Class instance. We can pass an absolute or relative path when locating a resource with a Class object.

现在,让我们看看如何使用Class实例获得资源。当用Class对象定位资源时,我们可以传递一个绝对或相对路径。

The rules for searching resources associated with a given class are implemented by the class loader of the class.

搜索与某一特定类相关的资源的规则由该类的加载器实现。

The process of finding the resource will be delegated to the class object’s class loader. In other words, the getResouce() method defined on the Class instance will eventually call ClassLoader‘s getResouce() method.

寻找资源的过程将被委托给类对象的类加载器。换句话说,定义在Class实例上的getResouce()方法将最终调用ClassLoadergetResouce()方法。

Before delegation, an absolute resource name will be derived from the given resource name. When creating the absolute resource name, the following algorithm will be used:

在委托之前,一个绝对资源名称将从给定的资源名称中导出。在创建绝对资源名称时,将使用以下算法。

  • If the resource name starts with a leading slash (“/”), it indicates the resource name is absolute. Absolute resource names are cleaned of their leading slash and are passed without any modification to the appropriate ClassLoader method to locate the resource.
  • If the provided resource name doesn’t start with a slash, the name is treated as relative to the class’s package. Relative names are first transformed to absolute and then are passed to the ClassLoader method.

Firstly, let’s suppose we have the example.txt resource defined inside the com/bealdung/resource directory. Furthermore, let’s assume we have the class ClassGetResourceExample defined inside the com.baeldung.resource package.

首先,让我们假设在com/bealdung/resource目录下定义了example.txt资源。此外,我们假设在com.baeldung.resource包中定义了ClassGetResourceExample类。

Now, we can retreive the resource using the absolute path:

现在,我们可以使用绝对路径检索资源了。

void givenAbsoluteResourcePath_whenGetResource_thenReturnResource() {
    URL resourceAbsolutePath = ClassGetResourceExample.class
        .getResource("/com/baeldung/resource/example.txt");
    Assertions.assertNotNull(resourceAbsolutePath);
}

When using Class.getResource(), absolute resource paths should begin with the leading slash.

当使用Class.getResource()时,绝对资源路径应该以前面的斜线开始。

Additionally, since our resource is inside the same package as our class, we can retrieve it using a relative path as well:

此外,由于我们的资源和我们的类在同一个包里,我们也可以用相对路径来检索它。

void givenRelativeResourcePath_whenGetResource_thenReturnResource() {
    URL resourceRelativePath = ClassGetResourceExample.class.getResource("example.txt");
    Assertions.assertNotNull(resourceRelativePath);
}

However, it’s important to mention that we can get the resource using a relative path only if the resource is defined inside the same package as a class. Otherwise, we’ll get a null as a value.

然而,值得一提的是,只有当资源被定义在与类相同的包内时,我们才能使用相对路径获取资源。否则,我们会得到一个null作为值。

4. ClassLoader.getResource()

4.ClassLoader.getResource()

As the name suggests, the ClassLoader represents a class responsible for loading classes. Every Class instance contains a reference to its ClassLoader.

顾名思义,ClassLoader代表一个负责加载类的类。每个Class实例都包含一个对其ClassLoader的引用。

The ClassLoader class uses a delegation model to search for classes and resources. Additionally, each instance of the ClassLoader class has an associated parent ClassLoader.

ClassLoader类使用一个委托模型来搜索类和资源。此外,每个ClassLoader类的实例都有一个相关的父ClassLoader

When asked to find a resource, the ClassLoader instance will first delegate the search to its parent ClassLoader before attempting to find the resource itself.

当被要求查找资源时,ClassLoader实例将首先委托其父ClassLoader进行搜索,然后再尝试自己查找资源。

In case a parent ClassLoader doesn’t exist, the path of the virtual machine’s built-in ClassLoader, called the bootstrap class loader, is searched. The bootstrap class loader doesn’t have a parent but may serve as a parent of a ClassLoader instance.

如果父级ClassLoader不存在,就会搜索虚拟机内置的ClassLoader的路径,称为引导类加载器。引导类加载器没有父类,但可以作为ClassLoader实例的父类。

Alternatively, the method will invoke the findResource() method to find the resource if the previous searches have failed.

另外,如果之前的搜索失败,该方法将调用findResource()方法来寻找资源。

The resource name specified as an input is always considered to be absolute. It’s important to note that Java loads resources from the classpath.

作为输入指定的资源名称总是被认为是绝对的。需要注意的是,Java从classpath加载资源。

Let’s get the resource using the absolute path and the ClassLoader instance:

让我们使用绝对路径和ClassLoader实例来获取资源。

void givenAbsoluteResourcePath_whenGetResource_thenReturnResource() {
    URL resourceAbsolutePath = ClassLoaderGetResourceExample.class.getClassLoader()
        .getResource("com/baeldung/resource/example.txt");
    Assertions.assertNotNull(resourceAbsolutePath);
}

When we call ClassLoader.getResource(), we should omit the leading slash when defining the absolute path.

当我们调用ClassLoader.getResource()时,我们应该在定义绝对路径时省略前面的斜线。

Using the ClassLoader instance, we cannot get resources using the relative path:

使用ClassLoader实例,我们无法使用相对路径获得资源

void givenRelativeResourcePath_whenGetResource_thenReturnNull() {
    URL resourceRelativePath = ClassLoaderGetResourceExample.class.getClassLoader()
        .getResource("example.txt");
    Assertions.assertNull(resourceRelativePath);
}

The test above demonstrates that the method returns a null value as a result.

上面的测试表明,该方法返回一个null值作为结果。

5. Conclusion

5.总结

This short tutorial explained the differences between calling the getResource() method from the Class and ClassLoader instances. To sum up, we can pass either a relative or an absolute resource path when calling the method using the Class instance, but we can only use the absolute path when calling the method on the ClassLoader.

这个简短的教程解释了从Class实例和ClassLoader实例调用getResource()方法的区别。总而言之,在使用Class实例调用该方法时,我们可以传递相对或绝对资源路径,但在ClassLoader上调用该方法时,我们只能使用绝对路径。

As always, the code is available over on GitHub.

一如既往,代码可在GitHub上获得