Class#getResource与ClassLoader#getResource分析
来源:互联网 发布:怎么做网络营销 知乎 编辑:程序博客网 时间:2024/06/10 03:53
- Class#getResource方法的参数path可以与以'/'开头的绝对路径或是不以'/'开头的相对路径,当以'/'开头时,会从classpath路径下获取资源,当不以'/'开头时,则从该类所在的包下获取资源,xxx.class.getResource() 即xxx.class类所在包。
- 而ClassLoader#getResource方法的参数却不能以'/'开头,其是从classpath下面获取资源。
来看看下面代码的结果
package com.jdk.resource;public class Resource { public static void main(String[] args) throws Exception { System.out.println(Resource.class.getResource("")); System.out.println(Resource.class.getResource("/")); System.out.println(Resource.class.getClassLoader().getResource("")); System.out.println(Resource.class.getClassLoader().getResource("/")); }}
结果:
file:/D:/workspace/JDKCore/bin/com/jdk/resource/file:/D:/workspace/JDKCore/bin/file:/D:/workspace/JDKCore/bin/null
可以看到Resource.class.getResource("")得到的路径classpath下Resource 类所在包,而Resource.class.getResource("/")为classpath根路径;而Resource.class.getClassLoader().getResource("")同样为classpath根路径,Resource.class.getClassLoader().getResource("/")则为空。 下面来看看Class#getResource方法的源码
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); }
从 cl.getResource(name)一行可以看出,Class#getResource方法最终还是调用了CalssLoader#getResource方法。再来看看name = resolveName(name)的实现,做了什么处理,其调用了Class类的resolveName方法
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; }
可以看出,resolveName方法的目的是当参数name以'/'开头就将'/'去除再返回,而当不以'/'开头则根据这个类对应的带包名全称变换成具体的路径名,如com.jdk.resource替换成com/jdk/resource。
现在应该明白最开始那个Resource 类中main方法的结果,实际上Class#getResource方法是去调CalssLoader#getResource的方法,只是在调用时会去判断是从相对路径还是绝对路径获取资源。不过api是有一点点坑Class#getResource以'/'开头与ClassLoader#getResource相同,再记住ClassLoader#getResource不能以'/'开头就行了。
有了前面这个Classr#getResource与ClassLoader#getResource的对比,Class#getResourceAsStream与ClassLoader#getResourceAsStream其实也就ok了。
Class#getResourceAsStream源码:
public InputStream getResourceAsStream(String name) { name = resolveName(name); ClassLoader cl = getClassLoader0(); if (cl==null) { // A system class. return ClassLoader.getSystemResourceAsStream(name); } return cl.getResourceAsStream(name); }
ClassLoader#getResourceAsStream源码:
public InputStream getResourceAsStream(String name) { URL url = getResource(name); try { return url != null ? url.openStream() : null; } catch (IOException e) { return null; } }
所以,可以用下面三种方式得到资源
- 利用Class#getResourceAsStream方法根据绝对路径从classpath下面得到,参数path以'/'开头
- 利用Class#getResourceAsStream方法根据类所处包的相对路径得到,参数path不能以'/'开头
- 利用ClassLoader#getResourceAsStream方法根绝对路径从classpath下面得到,参数path不能以'/'开头
在com.jdk.resource目录下创建一个test.properties文件,可以用以下三种方式得到
package com.jdk.resource;public class Resource { public static void main(String[] args) throws Exception { //第一种方式 System.out.println(Resource.class.getResourceAsStream("test.properties")); //第二种方式 System.out.println(Resource.class.getResourceAsStream("/com/jdk/resource/test.properties")); //第三种方式 System.out.println(Resource.class.getClassLoader().getResourceAsStream("com/jdk/resource/test.properties")); }}
结果:
java.io.BufferedInputStream@659e0bfdjava.io.BufferedInputStream@2a139a55java.io.BufferedInputStream@15db9742
这对查看,Spring Resource 接口的实现ClassPathResource类getInputStream方法有一定帮助
public InputStream getInputStream() throws IOException { InputStream is; if (this.clazz != null) { is = this.clazz.getResourceAsStream(this.path); } else if (this.classLoader != null) { is = this.classLoader.getResourceAsStream(this.path); } else { is = ClassLoader.getSystemResourceAsStream(this.path); } if (is == null) { throw new FileNotFoundException(getDescription() + " cannot be opened because it does not exist"); } return is; }
- Class#getResource与ClassLoader#getResource分析
- Class.getResource和ClassLoader.getResource区别与分析
- Class.getResource与ClassLoader.getResource()区别
- Class.getResource与ClassLoader.getResource()区别
- Class.getResource()与ClassLoader.getResource()区别
- Class.getResource vs ClassLoader.getResource
- Class.getResource vs ClassLoader.getResource
- Class.getResource vs ClassLoader.getResource .
- Class.getResource() and ClassLoader.getResource()
- Class.getResource vs ClassLoader.getResource
- Class.getResource vs ClassLoader.getResource
- Class.getResource和ClassLoader.getResource
- Class.getResource和ClassLoader.getResource
- Class.getResource和ClassLoader.getResource
- Class.getResource VS ClassLoader.getResource
- java Class.getResource和ClassLoader.getResource的区别分析
- Class.getResource和ClassLoader.getResource的区别分析
- Class.getResource和ClassLoader.getResource的区别分析
- java设计模式之简单工厂模式
- angular使用bootstrap方法手动启动
- iOS--内存分析工具
- mysql嵌套语句查询
- 让UITableView支持长按拖动排序(Swift)
- Class#getResource与ClassLoader#getResource分析
- mysql的定时任务学习
- OC
- 不重新编译PHP为PHP安装zlib扩展-学习收集
- I00037 亏数(Deficient number)
- 【GLSL教程】(七)逐像素的光照
- # Java中遍历Object的属性和属性值,并以String形式返回||toString()一个对象Object||将一个对象转化为字符串String
- Caffe中卷基层和全连接层训练参数个数如何确定
- 小瘦牛虚拟无线路由器官方版