千家信息网

Java怎么使用类路径获取资源

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,本篇内容介绍了"Java怎么使用类路径获取资源"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Java
千家信息网最后更新 2026年11月01日Java怎么使用类路径获取资源

本篇内容介绍了"Java怎么使用类路径获取资源"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

Java 可通过以下几种方法来访问资源:

  • Class 的 getResource 方法

  • ClassLoader 的 getResource 方法

  • ClassLoader 的 getSystemResource 静态方法

在使用中,Class 可通过直接引用类的 class 属性而获得,或是通过实例的 getClass() 方法来获得。获取 ClassLoader 的方式则比较多,常见以下几种:

  • 调用 Class 的 getClassLoader 方法,如:getClass().getClassLoader()

  • 由当前线程获取 ClassLoader:Thread.currentThread().getContextClassLoader()

  • 获取系统 ClassLoader: ClassLoader.getSystemClassLoader()

不过,若是对 Java 的 ClassLoader 概念不太了解,最好还是尽量避免使用它。

Class.getResource 与 ClassLoader.getResource 的区别

这两种方式,都接受一个字符串形式的路径表达式,即资源名,并返回找到的资源的 URL。两种方式都可用来定位资源,在网络上流传的文章中,两者都是常见的。实际上,Class 的 getResource 方法也调用了 ClassLoader 的 getResource 方法,但两者有着很大的不同,不了解这两种方法的区别,就容易造成隐患。隐患经常比编写时就出错要可怕得多,因为它在一定场合下是正常的,不容易被发现。

两者最大的区别,是从哪里开始寻找资源。ClassLoader 并不关心当前类的包名路径,它永远以 classpath 为基点来定位资源。而 Class.getResource 则不同,如果资源名是绝对路径(以"/"开头),它会将开头的"/"去除,然后调用 ClassLoader 的 getResource 方法来寻找资源;如果资源名是相对路径,它会在当前的包路径下面寻找资源。

举例来说,假设我们有一个类:test.App (包名为 test),并且在 test 包下有一个与类名同名的 js 文件,名为 App.js。如果用 ClassLoader 来获取这个 js 文件,应该这样写:

App.class.getClassLoader().getResource("test/App.js");

如果用 Class 的 getResource 方法,则有两种写法:

  • 使用相对路径:

App.class.getResource("App.js");
  • 使用绝对路径:

App.class.getResource("/test/App.js");

从上面的例子,可以看出两者之间巨大的区别。有些人从网络上复制类似的代码,看看不能正确运行,就开始尝试在资源名前加上 "/",或是去掉开头的 "/",试成功了,便算完工,这绝非正道。

Class 与 ClassLoader 的 getResource 方法还有其它一些不同,对 Class 的 getResource 方法来说,若传入的是相对路径,它还会尝试做包名与路径名的转换。查看 Class.getResource 方法的源码,可以看到它首先对资源名调用了 resolveName 方法,然后再调用 ClassLoader 的 getResource 方法来完成资源的定位。

测试代码

作为演示,我写了以下代码来展示 Class 与 ClassLoader 的 getResource 方法的输出:

/** * Copyright (c) 2014 Chen Zhiqiang . Released under the MIT license. */package test;import java.net.URL;import java.util.Enumeration;/** * Tests for the use of {@link Class#getResource(String)} and * {@link ClassLoader#getResource(String)}. *  * @author Chen Zhiqiang  */public class ClassResourceTest {    Class cls = ClassResourceTest.class;    ClassLoader ldr = cls.getClassLoader(); // Thread.currentThread().getContextClassLoader()    public static void println(Object s) {        System.out.println(s);    }    void showResource(String name) {        println("## Test resource for: "" + name + "" ##");        println(String.format("ClassLoader#getResource("%s")=%s", name, ldr.getResource(name)));        println(String.format("Class#getResource("%s")=%s", name, cls.getResource(name)));    }    public final void testForResource() throws Exception {        showResource("");        showResource("/");        showResource(cls.getSimpleName() + ".class");        String n = cls.getName().replace('.', '/') + ".class";        showResource(n);        showResource("/" + n);        showResource("java/lang/Object.class");        showResource("/java/lang/Object.class");    }    public static void main(String[] args) throws Exception {        println("java.class.path: " + System.getProperty("java.class.path"));        println("user.dir: " + System.getProperty("user.dir"));        println("");        ClassResourceTest t = new ClassResourceTest();        t.testForResource();    }}

编译上述代码,看看不同资源路径的输出结果。

打包为 Jar 包后的变化

现在,将上述代码编译后的结果打包成 Jar 文件,假设是 test.jar ,然后从这个 jar 包中运行上述代码,再看看输出结果,比较下与上面的输出有什么变化:

java -classpath test.jar test.ClassResourceTest

值得注意的几点:

  • Class.getResource("") 还有其它一些输出,结果是 jar:file:/some_path/test.jar!/some_path,而在打包为 Jar 之前,它们的输出形式是 file:/some_path...;

  • Class.getResource("/") 为 null,而在打包之前,该输出是 ClassResourceTest 的类路径;

  • ClassLoader.getResource("") 为 null,而在打包之前,该输出是 ClassResourceTest 的类路径;

  • 调用 ClassLoader.getResource 方法时,若资源名为绝对路径,不管是否打包,其输出结果为 null,至少在我这里是这样。

错误与陷阱

  • 使用 Class.getResource("/") 或 ClassLoader.getResource("") 来当作类路径的根。

这是一种常见的错误,并在网络上广为流传。它们在打包成 Jar 包后,其结果会发生变化。

  • 获得 getResource 方法的输出后,简单地对结果调用 getFile 或 getPath,并把它当作文件路径来处理。

资源有可能以文件和目录的形式位于类路径之中,但也可能打包进了 Jar 包或 Zip 包,你不能假设你的代码不会被打包。

  • 将绝对路径传给 ClassLoader 的 getResource 方法。

网络上有人说,对于 ClassLoader 的 getResource 方法来说,资源名是否以 "/" 开头是一样的,然而,在我这里,ClassLoader 的 getResource 方法并不接受绝对路径,其输出结果为 null。

正确使用 getResource 方法

  • 避免使用 Class.getResource("/") 或 ClassLoader.getResource("")。你应该传入一个确切的资源名,然后对输出结果作计算。比如,如果你确实想获取当前类是从哪个类路径起点上执行的,以前面提到的 test.App 来说,可以调用 App.class.getResource(App.class.getSimpleName() + ".class")。如果所得结果不是 jar 协议的URL,说明 class 文件没有打包,将所得结果去除尾部的 "test/App.class",即可获得 test.App 的类路径的起点;如果结果是 jar 协议的 URL,去除尾部的 "!/test/App.class",和前面的 "jar:",即是 test.App 所在的 jar 文件的 url。

  • 如果要定位与某个类同一个包的资源,尽量使用那个类的getResource方法并使用相对路径。如前文所述,要获取与 test.App.class 同一个包下的 App.js 文件,应使用 App.class.getResource("App.js") 。当然,事无绝对,用 ClassLoader.getResource("test/App.js") 也可以,这取决于你所面对的问题是什么。

  • 如果对 ClassLoader 不太了解,那就尽量使用 Class 的 getResource 方法。

  • 如果不理解或无法确定该传给 Class.getResource 方法的相对路径,那就以类路径的顶层包路径为参考起点,总是传给它以 "/" 开头的路径吧。

  • 不要假设你的调试环境就是最后的运行环境。你的代码可能不打包,也可能打包,你得考虑这些情况,不要埋坑。

getResources: 枚举资源

Java 的 CLASSPATH 是一个路径列表,因此,有可能在多个类路径中出现同样的资源名。如果要列举它们,可以使用 ClassLoader 的 getResources 方法。

下面的代码可以枚举所有的 "META-INF/MANIFEST.MF",你还可以观察到在类路径中哪些 jar 文件包含有该资源:

import java.net.URL;import java.util.Enumeration;public class Test {    public static void main(String[] args) throws Exception {        ClassLoader ldr = Test.class.getClassLoader();        System.out.println("## Test for getResources('META-INF/MANIFEST.MF') ##");        Enumeration urls = ldr.getResources("META-INF/MANIFEST.MF");        while(urls.hasMoreElements())            System.out.println(urls.nextElement());    }}

实例

下面的代码演示了如何正确获取代码的类路径起点:

/** * Copyright (c) 2014 Chen Zhiqiang . Released under the MIT license. */package test;import java.io.File;import java.net.MalformedURLException;import java.net.URL;import java.util.regex.Matcher;import java.util.regex.Pattern;/** * 演示如何获取当前类路径的起点 *  * @author Chen Zhiqiang  */public class AppDirTest {        Classcls = AppDirTest.class;        URL codeLocation = getCodeLocation();        /**         * Get the code location.         *          * Return the classpath where the code run from. The return url will be:         *   file:/path/my-app/calsses/ or file:/path/my-app/my-app.jar         *         * @return URL         */        public URL getCodeLocation() {                if (codeLocation != null)                        return codeLocation;                // Get code location using the CodeSource                codeLocation = cls.getProtectionDomain().getCodeSource().getLocation();                if (codeLocation != null)                        return codeLocation;                // If CodeSource didn't work, use {@link } Class.getResource instead.                URL r = cls.getResource("");                synchronized (r) {                        String s = r.toString();                        Pattern jar_re = Pattern.compile("jar:\s?(.*)!/.*");                        Matcher m = jar_re.matcher(s);                        if (m.find()) { // the code is run from a jar file.                                s = m.group(1);                        } else {                                String p = cls.getPackage().getName().replace('.', '/');                                s = s.substring(0, s.lastIndexOf(p));                        }                        try {                                codeLocation = new URL(s);                        } catch (MalformedURLException e) {                                throw new RuntimeException(e);                        }                }                return codeLocation;        }        /**         * Get the class path root where the program startup, if run in a jar,         * return the jar file's parent path.         *          * @return         */        public String getAppDir() {                File f = new File(getCodeLocation().getPath());                return f.isFile() ? f.getParent() : f.getPath();        }        public static void main(String[] args) {                AppDirTest t = new AppDirTest();                System.out.println("code location: " + t.getCodeLocation());                System.out.println("app dir: " + t.getAppDir());        }}

"Java怎么使用类路径获取资源"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

路径 方法 资源 输出 结果 代码 文件 开头 起点 不同 网络 面的 定位 常见 形式 方式 变化 演示 运行 内容 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网科技名片 广州百单互联网科技有限公司 鑫亿盛互联网科技 深圳期待互联网科技 互联网科技英文翻译 佰商互联网科技有限公司 互联网科技中介 互联网科技创新服务 互联网金融中的现代科技 南平创想时代互联网科技有限公司 互联网与医疗科技 呼和浩特新华互联网科技学院 青海科技产业互联网发展 允成互联网科技有限公司融资 烟台灵鸽互联网科技有限公司 工业互联网科技成果转化 信承诺互联网科技有限公司 济南小医互联网科技有限公司招聘 广州三三互联网科技有限公司 科技互联网公司两年变化 中关村互联网 科技集团 与互联网科技公司 互联网科技的未来发展 天速互联网络科技有限公司 济南华为互联网科技产业总部基地 受益于互联网科技的高速发展 新兴科技互联网创新大赛颁奖典礼 玉溪互联网科技怎么选 企晟互联网信息科技有限公司 互联网科技博主张洲
0