Class与Classloader的getResourceAsStream()与getResource()读取资源文件

一.含义与区别

1. 类.class.getResource(String path):
我们经常用getResourceAsStream来获取配置文件信息,也有2种方式getResourceAsStream,一种是class.getResourceAsStream,
另一种是classloader.getResourceAsStream,这2种方式有什么区别呢?
class.getResourceAsStream(“path”):从当前class的目录下找资源
class.getResourceAsStream("/path");/代表了class的包名,也就是从root classpath寻找资源
而对于classloader.getResourceAsStream(“path”),只有这种方式有效,效果同class.getResourceAsStream("/path"),从根目录去找。
总结:path不以’/‘开头时,默认是从此类所在的包下取资源(类所在的最下一级包);
        path以’/‘开头时,则是从项目的ClassPath类路径下获取资源。在这里’/'表示ClassPath的根目录。

2. 类.class.getClassLoader().getResource(String path):
含义:从项目的ClassPath类路径下下获取资源(path不能带’/’)。
path不能以’/'开头,path是指类加载器的加载范围,在资源加载的过程中,使用的逐级向上委托的形式加载的,’/'表示Boot ClassLoader,类加载器中的加载范围,因为这个类加载器是C++实现的,所以加载范围为null

扩展点:JAVA中类的加载器:一共有三种加载器
	1.bootstrap classloader :负责加载JAVA核心类( jre 下lib和class目录中的内容)
	2.extension classloader :负责加载JAVA扩展类(jre 下lib/ext 目录中的内容)
	3.system classloader :负责加载应用指定的类 (环境变量classpath中配置的内容)
一个类的加载顺序也是按上面的排列来的,这样就能保证系统的类能先加载。与此同时用户也可以自己定义ClassLoader,用来加载特殊的资源。
这里就涉及到 Class.getClassLoader()  和  Thread.currentThread.getContextClassLoader()的区别。
举一个简单的例子:假如某天JAVA给我们提供了一个叫 StartCamera 的类用来启动电脑的标准摄像头,并将这个类打包在一个jar中。   
正常情况下,我们要启动摄像头时只需将这个jar配置到classpath中。系统启动时system classloader会将这个类加载到应用中。
但因为摄像头的生产厂家不一样,针对新的设备会有多个不同的StartCamera实现,在应用中我们不知道实际的用户会用到哪种。
于是我们就自定义了一个ClassLoader,用来针对具体的设备类型加载相应的StartCamera类。这样一来就出现:优先加载我们定义的类,加载不到的情况下再加载系统的。 
这样的需求,是系统默认的父委托加载机制无法满足的。
例如Thread.currentThread.getContextClassLoader() 就是这样产生的。 
我们使用Thread.currentThread.setContextClassLoader() 可以为当前线程指定相应的ClassLoader,然后用get的方式来获取。

实例说明:Tools.class.getClassLoader().getResourceAsStream(file);      
首先,Tools.class是获得对象当前的类类型,这部分数据存在方法区中, 然后,在类类型上调用getClassLoader()方法是得到当前类型的类加载器,
在Java中所有的类都是通过加载器加载到虚拟机中的,而且类加载器之间存在父子关系,就是子知道父,父不知道子,
这样不同的子加载的类型之间是无法访问的(虽然它们都被放在方法区中),这样通过当前类的加载器来加载资源也就是保证是和类类型同一个加载器加载的。 
最后,调用了类加载器的getResourceAsStream()方法来加载文件资源。

3. 类.getResourceAsStream(String path):
path不以’/‘开头时,默认是指所在类的相对路径,从这个相对路径下取资源;
path以’/'开头时,则是从项目的ClassPath根下获取资源,就是要写相对于classpath类路径下的绝对路径。

4. 类.getClassLoader.getResourceAsStream(String path):
默认则是从ClassPath类路径下获取,path不能以’/'开头,最终是由ClassLoader获取资源。
如果以‘/’ 开头,则返回的是ClassLoader加载器Boot ClassLoader的加载范围,所以返回的也是null,所以不能以 / 开头。
class.getResourceAsStream最终调用是ClassLoader.getResourceAsStream,这两个方法最终调用还是ClassLoader.getResource()方法加载资源。所以上面的规则也适用于此。


注意:1. 我们使用ClassLoader.getResourceAsStream加载资源是不能带有前导 / 字符的。
           2. class.getResource("/") == class.getClassLoader().getResource("")。其实,Class.getResource和ClassLoader.getResource本质上是一样的,都是使用ClassLoader.getResource加载资源的。jdk的源码中,Class.getResource和ClassLoader.getResource本质上是一样的。至于为什么Class.getResource(String path)中path可以’/'开头,是因为在name = resolveName(name);进行了处理。
           3. Class.getResource(String path)和Class.getClassLoader().getResource(String path)规则相同,Class.getResourceAsStream(String path)和Class.getClassLoader().getResourceAsStream(String path)规则相同。


二.原始API

Class类的API:
在这里插入图片描述
在这里插入图片描述
ClassLoader的API:

在这里插入图片描述
在这里插入图片描述

三.例子

在这里插入图片描述

  • 4
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值