1. 概述
在这个简短的教程中,我们将了解Class.getResource()和ClassLoader.getResource()方法之间的区别。
2. getResource()方法
我们可以在Class或ClassLoader实例上使用getResource()方法来查找具有给定名称的资源。资源被认为是数据-例如图像、文本、音频等。作为路径分隔符,我们应该始终使用斜杠(“/”)。
该方法返回用于读取资源的URL对象,如果找不到资源或调用者没有检索资源的权限,则返回null值。
3. Class.getResource()
现在,让我们看看如何使用Class实例获取资源。在使用Class对象定位资源时,我们可以传递绝对路径或相对路径。
搜索与给定类关联的资源的规则由该类的类加载器实现。
查找资源的过程将委托给类对象的类加载器。换句话说,在Class实例上定义的getResource()方法最终将调用ClassLoader的getResource()方法。
在委派之前,绝对资源名称将从给定的资源名称派生。创建绝对资源名称时,将使用以下算法:
- 如果资源名称以斜杠(“/”)开头,则表示资源名称是绝对的。绝对资源名称将清除其前导斜杠,并在不进行任何修改的情况下传递给相应的ClassLoader方法以定位资源。
- 如果提供的资源名称不以斜杠开头,则该名称将被视为相对于类的包。相对名称首先转换为绝对名称,然后传递给ClassLoader方法。
首先,假设我们在cn/tuyucheng/taketoday/resource目录中定义了example.txt资源。此外,假设我们在cn.tuyucheng.taketoday.resource包中定义了类ClassGetResourceExample。
现在,我们可以使用绝对路径检索资源:
void givenAbsoluteResourcePath_whenGetResource_thenReturnResource() {
URL resourceAbsolutePath = ClassGetResourceExample.class
.getResource("/cn/tuyucheng/taketoday/resource/example.txt");
Assertions.assertNotNull(resourceAbsolutePath);
}
使用Class.getResource()时,绝对资源路径应以前导斜杠开头。
此外,由于我们的资源与我们的类在同一个包内,我们也可以使用相对路径检索它:
void givenRelativeResourcePath_whenGetResource_thenReturnResource() {
URL resourceRelativePath = ClassGetResourceExample.class.getResource("example.txt");
Assertions.assertNotNull(resourceRelativePath);
}
但是,重要的是要提到,只有当资源定义在与类相同的包中时,我们才能使用相对路径获取资源。否则,我们将得到一个null作为值。
4. ClassLoader.getResource()
顾名思义,ClassLoader代表一个负责加载类的类。每个Class实例都包含对其ClassLoader的引用。
ClassLoader类使用委托模型来搜索类和资源。此外,ClassLoader类的每个实例都有一个关联的父类ClassLoader。
当被要求查找资源时,ClassLoader实例将首先将搜索委托给其父ClassLoader,然后再尝试自行查找资源。
如果父ClassLoader不存在,则会搜索虚拟机内置ClassLoader的路径,称为引导类加载器。引导类加载器没有父类,但可以作为ClassLoader实例的父类。
或者,如果先前的搜索失败,该方法将调用findResource()方法来查找资源。
指定为输入的资源名称始终被认为是绝对的,重要的是要注意Java从类路径加载资源。
让我们使用绝对路径和ClassLoader实例获取资源:
void givenAbsoluteResourcePath_whenGetResource_thenReturnResource() {
URL resourceAbsolutePath = ClassLoaderGetResourceExample.class.getClassLoader()
.getResource("cn/tuyucheng/taketoday/resource/example.txt");
Assertions.assertNotNull(resourceAbsolutePath);
}
当我们调用ClassLoader.getResource()时,我们应该在定义绝对路径时省略前导斜杠。
使用ClassLoader实例,我们无法使用相对路径获取资源:
void givenRelativeResourcePath_whenGetResource_thenReturnNull() {
URL resourceRelativePath = ClassLoaderGetResourceExample.class.getClassLoader()
.getResource("example.txt");
Assertions.assertNull(resourceRelativePath);
}
上面的测试表明该方法返回一个null值作为结果。
5. 总结
这个简短的教程解释了从Class和ClassLoader实例调用getResource()方法之间的区别。综上所述,我们在使用Class实例调用方法时可以传递相对或绝对资源路径,但在调用ClassLoader方法时只能使用绝对路径。
与往常一样,本教程的完整源代码可在GitHub上获得。