Class.getResource和ClassLoader.getResource区别与分析

零、 前言

在一个获取文件路径的代码内容上发现单元测试出现NullPointer, 但是这段代码却在服务器正常运行了两年多, 借此机会想认真探索下这两个方法的区别。

一、 区别

区别从代码输出结果来看比较清晰,

文件结构图:

以下为在多个场景下使用方式的代码:

package com.wenniuwuren.test;

/**
 * 获取文件路径
 * Created by wenniuwuren on 15/8/14.
 */
public class GetResourceTest {

    public static void main(String[] args) {

        // 带 “/” 的其实就是返回根目录
        System.out.println("GetResourceTest.class.getResource(\"/\") -----> "
                + GetResourceTest.class.getResource("/"));

        System.out.println("GetResourceTest.class.getResource(\"/DD.DD\") -----> "
                + GetResourceTest.class.getResource("/DD.DD"));

        // *************************************************

        // 返回当前路径
        System.out.println("GetResourceTest.class.getResource(\"\") -----> "
                + GetResourceTest.class.getResource(""));

        System.out.println("GetResourceTest.class.getResource(\"AA.AA\") -----> "
                + GetResourceTest.class.getResource("AA.AA"));

        System.out.println("GetResourceTest.class.getResource(\"subtest/BB.BB\") -----> "
                + GetResourceTest.class.getResource("subtest/BB.BB"));

        System.out.println("GetResourceTest.class.getResource(\"../CC.CC\") -----> "
                + GetResourceTest.class.getResource("../CC.CC"));

        // 查找classloader root。 用 getClassLoader 最容易出问题, 因为是根据类加载器来的, 类加载器多种多样可能在不同环境下产生不同结果
        GetResourceTest getResourceTest = new GetResourceTest();
        System.out.println("getResourceTest.getClass().getClassLoader().getResource(\"\") -----> "
                + getResourceTest.getClass().getClassLoader().getResource(""));

        System.out.println("getResourceTest.getClass().getClassLoader().getResource(\"/\") -----> "
                + getResourceTest.getClass().getClassLoader().getResource("/"));

        /**
         * 从输出结果来看总结上述: Class.class.getResource("/")  ==  Class.getClass().getClassLoader().getResource("")
         */

        // 这是一种可以避免在不同Web容器下获取路径异常的方法
        System.out.println("GetResourceTest.class.getProtectionDomain().getCodeSource().getLocation().getPath() -----> "
                + GetResourceTest.class.getProtectionDomain().getCodeSource().getLocation().getPath());
    }

}

二、 从源码角度分析

分析前先看个 Java 类加载的架构图, 有助于下文理解:

1. Class.getResource

算法基本为: 搜索策略为此类关联的类加载器实现的, 即这个方法委托给这个对象的类加载器,如果对象是被 Bootstrap 类加载器加载的, 则进入 ClassLoader.getSystemResource() 方法, 这个方法先找系统级别的类加载器(这个加载器是一般应用启动的类加载器), 如果找不到则使用虚拟机内置的类加载器。

如果传的参数是“/”则返回根路径, 传的是具体文件名就返回文件绝对路径。

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);
    }

2. ClassLoader.getResource

会先从父加载器去找资源, 如果父加载器为 null 则从虚拟机内置加载器去查找(这步何上面最后一步相同), 如果还没有, 则去findResource() [可以重写这个方法自己实现个类加载器去寻找资源]去找。

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;
    }

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-13 22:26:06

Class.getResource和ClassLoader.getResource区别与分析的相关文章

Class.getResource和ClassLoader.getResource的区别分析

Class.getResource(String path)path不以'/'开头时,默认是从此类所在的包下取资源:path以'/'开头时,则是从项目的ClassPath根下获取资源.在这里'/'表示ClassPathJDK设置这样的规则,是很好理解的,path不以'/'开头时,我们就能获取与当前类所在的路径相同的资源文件,而以'/'开头时可以获取ClassPath根下任意路径的资源.如下所示的例子: 1 2 3 4 5 6 7 8 public class Test { public stat

myBatis中的注解@Param、返回值为Map、JAVA读取Excel并解析文本、Class.getResource()和ClassLoader.getResource()

myBatis中的注解@Param:http://blog.csdn.net/gao36951/article/details/44258217:  http://www.cnblogs.com/thomas12112406/p/6217211.html. myBatis返回值为Map:http://blog.csdn.net/werewr342352321df/article/details/11892755. ====================== JAVA读取Excel并解析文本:h

[Java开发之路](18)关于Class.getResource和ClassLoader.getResource的路径问题

Java中取资源时,经常用到Class.getResource和ClassLoader.getResource.昨天老师讲解题目时候,问我们为什么你们都是在文件前家上"/": String path = Resources.class.getResource("/a.txt").getPath(); 注:在Resources文件下创建了a.txt文件 我想我反正是试出来的,不使用"/"不行.为了正式解答心中的疑惑,我们正式来看看Resources

关于Class.getResource和ClassLoader.getResource的路径问题

Java中取资源时,经常用到Class.getResource和ClassLoader.getResource,这里来看看他们在取资源文件时候的路径问题. 转自:http://www.cnblogs.com/yejg1212/p/3270152.html Class.getResource(String path) path不以’/'开头时,默认是从此类所在的包下取资源: path 以’/'开头时,则是从ClassPath根下获取: 什么意思呢?看下面这段代码的输出结果就明白了: package

Class.getResource和ClassLoader.getResource的路径写法

Java中取资源时,经常用到Class.getResource和ClassLoader.getResource,这里来看看他们在取资源文件时候的路径问题. Class.getResource(String path) path 不以’/'开头时,默认是从此类所在的包下取资源:以’/'开头时,则是从ClassPath根下获取: 同样用法的还有Class.getResource和Class.getResourceAsStream. Class.getClassLoader().getResource

Java Class.getResource和ClassLoader.getResource的使用

Java中获取资源文件的时候,经常会用到Class.getResource和ClassLoader.getResource,本文给大家说一下这两者方法在获取资源文件时的路径差异. Class.getResource(String path) path不以'/'开头时,默认是从此类所在的包下取资源: path以'/'开头时,则是从项目的ClassPath根下获取资源.在这里'/'表示ClassPath JDK设置这样的规则,是很好理解的,path不以'/'开头时,我们就能获取与当前类所在的路径相同

class.getResource与classloader.getResource

前言 之前偶然看到一篇别人写的文章 https://www.cnblogs.com/drwong/p/5389631.html .对于怎么找到classpath下的资源,比如图片呀,视频呀什么的..勾起了我的一点好奇心. 现在大家项目一般都是springboot的.那加载资源还是比较简单的..比如ClassPathResource呀..PathMatchingResourcePatternResolver呀(没有仔细确认,但是我印象中mybatis整合spring-boot的时候是用这个类去加载

关于Class.getResource和ClassLoader.getResource的路径问题(转)

参考博客:http://www.cnblogs.com/yejg1212/p/3270152.html Class.getResource(String path) 当path以/开头,如/a/b/c.properties时,查找的路径为: classpath路径:path. 当path不以/开头时,如c.properties,查找的路径为:当前调用类的路径:path. 什么意思呢?看下面这段代码的输出结果就明白了: package testpackage; public class TestM

Class和ClassLoader.getResource获取资源

资源就是系统内.项目内的各种文件.在Java中获取可以用File类和Class.getResource获取资源,直观的说,File是依赖于文件系统和操作系统的,通过相对和绝对路径定位,使用File接口可以用于获取系统内任何路径下的普通文件.Class和ClassLoader可以用于获取项目环境中的资源,'环境中'的具体定义就是classpath.classpath相当于getResource参数的跟目录,ClassLoader.getResource是只能从这个根目录开始定位资源,Class.g