Java(47):学习Class.getResource和ClassLoader.getResource

====》getResource方法是得到文件路径的函数。

获取文件的路径,使用时主要是两种方法, 一个是字节码文件Class类, 另一个是ClassLoader类加载器

使用Class类时有两种使用方式:

1、不使用"/" 这就是具体该类的路径

2、使用"/"  获取到的是classpath路径

ClassLoader类

1、没有"/"的写法, 直接写文件名获取到的就是classpath路径

其实如果读取class下面的这里就用:

PropertiesUtil.class.getClassLoader().getResource("").getPath()获取就可以。

System.out.println(PropertiesUtil.class.getResource("").getPath());  -->PropertiesUtil.class类所在的位置

System.out.println(PropertiesUtil.class.getResource("/").getPath());  -->classpath的路径

System.out.println(PropertiesUtil.class.getClassLoader().getResource("").getPath());-->classpath的路径

System.out.println(PropertiesUtil.class.getClassLoader().getResource("/"));  -->classpath的路径

一、Class.getResource源码解析

看下具体例子:

 看下System.out.println(PropertiesUtil.class.getResource("").getPath());的调用。

方法getResource("")的源码:

public java.net.URL getResource(String name) {
        name = resolveName(name);
        ClassLoader cl = getClassLoader0();   // 获取加载该Class的ClassLoader
        if (cl==null) {//如果加载该Class的ClassLoader为null,则表示这是一个系统class
            // A system class.
            return ClassLoader.getSystemResource(name);  
        }
        return cl.getResource(name); /调用ClassLoader的getResource方法
    }

下面是ClassLoader的getResource方法

public java.net.URL getResource(String name) {
        name = resolveName(name);
        ClassLoader cl = getClassLoader0();   // 获取加载该Class的ClassLoader
        if (cl==null) {//如果加载该Class的ClassLoader为null,则表示这是一个系统class
            // A system class.
            return ClassLoader.getSystemResource(name);  
        }
        return cl.getResource(name); /调用ClassLoader的getResource方法
    }

下面是ClassLoader的getResource方法

public URL getResource(String name) {
        URL url;
        if (parent != null) {  //这里的parent为sun.misc.Launcher$ExtClassLoader@7d4793a8
            url = parent.getResource(name);//这里是一个递归调用,再次进入之后parent为null
        } else {
            url = getBootstrapResource(name);//到达系统启动类加载器
        }
        if (url == null) {//系统启动类加载器没有加载到,递归回退到第一次调用然后是扩展类加载器
            url = findResource(name);
        }
        return url;//最后如果都没有加载到,双亲委派加载失败,则加载应用本身自己的加载器
    }

getResource()方法中name = resolveName(name);

 private String resolveName(String name) {
        if (name == null) {
            return name;
        }
        if (!name.startsWith("/")) { -->//对于不以/开头的文件,
            Class<?> c = this;  //获取当前加载类的完整的类路径,例如:/com/ciphergateway/utils/
            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;
    }

具体说明:

Class.getResource和ClassLoader.getResource 最终调用的是ClassLoader 类的getResource方法。只不过Class.getResource是先调用Class 的 getResource 方法,在这个getResource  方法中,再去调用ClassLoader 类的getResource方法。

二、对于:class.getResource("")

1、PropertiesUtil.class.getResource("").getPath()

Class类中的getResource方法返回的是/com/ciphergateway/utils/ (获取当前加载类的完整的类路径)

ClassLoader类中的getResource方法返回的是

 /D:/java_project2021/autocasb/target/classes/com/ciphergateway/utils/

这里获取的文件路径其实是:/D:/java_project2021/autocasb/target/classes/com/ciphergateway/utils/

  1. PropertiesUtil.class.getResource("/").getPath()

Class类中的getResource方法返回的是""

ClassLoader类中的getResource方法返回的是 file:/C:/myroad/utalitityUtils/target/classes/

  1. PropertiesUtil.class.getClassLoader().getResource("").getPath()

class.getClassLoader().getResource("")返回的是target/class/

这里获取的文件路径其实是:/D:/java_project2021/autocasb/target/classes

三、对于ClassLoader.getResource

PropertiesUtil.class.getClassLoader().getResource("").getPath()

直接调用的就是ClassLoader 类的getResource方法,那么对于getResource(""),通过当前类加载classpath根下资源文件。

所以这里的路径是:/D:/java_project2021/autocasb/target/classes

四、Class.getResource和ClassLoader.getResource的区别

就是在加载资源文件的时候,加载方式的不同,

class.getResource("/") == class.getClassLoader().getResource("")

其实,Class.getResource和ClassLoader.getResource本质上是一样的,都是使用ClassLoader.getResource加载资源的。

Class.getResource真正调用ClassLoader.getResource方法之前,会先获取文件的路径(path不以'/'开头时,默认是从此类所在的包下取资源;path以'/'开头时,则是从项目的ClassPath根下获取资源)。

ClassLoader.getResource方法会通过双亲委派机制,先委派双亲去加载类,如果双亲没有加载到,则再由自己加载。

classLoader加载顺序,详见https://blog.csdn.net/eff666/article/details/52203406

参考:

https://blog.csdn.net/zhangshk_/article/details/82704010

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宁儿测试开发

您的鼓励是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值