1.getResource()获取文件路径方法
在编写java程序的时候,有时候需要从resource文件夹中加载资源文件。这时可以使用以下方式来获取资源文件路径:
TheClass.class.getResource(java.lang.String).getPath();
or
TheInstanceOfTheClass.getClass().getResource(java.lang.String).getPath();
2.getResource()源码以及官方文档方法说明
有关方法说明,官方文档链接点这里。java.lang.Class#getResource方法源码(其中传入参数(java.lang.String)name为希望加载的资源文件名称):
public java.net.URL getResource(String name) {
name = resolveName(name);
ClassLoader cl = getClassLoader0();
if (cl==null) {
// A system class.
return ClassLoader.getSystemResource(name);
}
return cl.getResource(name);
}
resolveName(name)解析资源文件名称:
private String resolveName(String name) {
if (name == null) {
return name;
}
if (!name.startsWith("/")) {
Class<?> c = this;
while (c.isArray()) {
c = c.getComponentType();
}
String baseName = c.getName();
int index = baseName.lastIndexOf('.');
if (index != -1) {
name = baseName.substring(0, index).replace('.', '/')
+"/"+name;
}
} else {
name = name.substring(1);
}
return name;
}
其中name参数格式有两种方式:
-
如果参数以'
/' ('\u002f')符号开始则执行name.substring(1),即资源文件名称实际为'/' ('\u002f')符号后面的部分。ex:若name为“/config.config”则文件名称为config.config -
否则,
resolveName(String name)会找到这个类的名称,把其中“/”('\u002f')代替名称中的“.” ('\ u002e')符号,接着拼接传入的name参数。因此传入的资源文件名称name为以下格式modified_package_name/name。其中modified_package_name为此资源文件相对于此类的包名,用“/”('\u002f')代替“.” ('\ u002e')。ex:若TheClass类文件在com.example包中,资源文件相对于类路径为/config的时候,应传入name为config/config.config,经过resolveName(name)方法处理后返回name为com/example/config/config.config。
关于搜索资源文件的规则,由该类的定义类加载器实现。
首先,此方法委托给这个类的类加载器,但是当这个类的加载器为引导类加载器时候,此方法就会委托给 ClassLoader.getSystemResource(java.lang.String)方法。经过类加载器将名称转换为文件名,然后从文件系统中读取该资源文件。
3.类加载器加载资源文件
有关类加载器说明,官方文档链接点这里。java.lang.ClassLoader#getResource方法源代码(此方法返回值为:1.资源文件对象,2.当调用没有足够权限或者没有找到的情况下为null):
public URL getResource(String name) {
URL url;
if (parent != null) {
url = parent.getResource(name);
} else {
url = getBootstrapResource(name);
}
if (url == null) {
url = findResource(name);
}
return url;
}
ClassLoader类使用委托模型来搜索类和资源。类加载器的每个实例都有一个关联的父类加载器。当请求查找类或资源时,类加载器实例将把对类或资源的搜索委托给其父类加载器,然后再尝试查找类或资源本身。
虚拟机的内置类加载器称为“引导类装入器”,它本身没有父类加载器,但可以作为类加载器实例的父类。(下图为类加载器委托模型,来源:www.geeksforgeeks.org/classloader-in-java/,侵删)
4.示例
示例目录结构:
|-- Java
|-- src
|-- main
|-- java
|-- example
|-- GetResource.java
|-- resources
|-- example
|-- config.config
public static void main(String[] args) {
System.out.println(
GetResource.class.getResource(
"config.config"
).getPath()
);
}
结果为:
D:/work/myproject/springBoot/HelloWorldApp/Java/target/classes/example/config.config
debug的大致调用顺序为:
1.java.lang.Class#getResource=>
2.java.lang.ClassLoader#getResource=>
3.java.lang.ClassLoader#getResource=>
4.java.lang.ClassLoader#getBootstrapResource=>
5.java.lang.ClassLoader#getResource=>
6.java.net.URLClassLoader#findResource=>
7.java.lang.ClassLoader#getResource=>
8.java.lang.ClassLoader#getResource=>
9.java.net.URLClassLoader#findResource(命中)=>
10.java.lang.ClassLoader#getResource=>
11.java.lang.Class#getResource
5.总结
1.getResource()方法中参数有两种格式
2.getResource()此方法委托类加载器加载资源
3.类加载器使用委托模型
6.reference
[1]docs.oracle.com/javase/8/do…