主要说明二者的区别以及使用上的注意事项
二者作用: 在当前 classpath 下, 获取资源
public class Demo{ public static void main(String[] params){ String path = ""; //todo 使用当前类的 Class 对象调用 Demo.class.getResource(path); Demo.class.getResourceAsStream(path); //todo 使用当前类的加载器调用 Demo.class.getClassLoader().getResource(path); Demo.class.getClassLoader().getResourceAsStream(path); //todo 使用当前线程的所在上下文的类加载器调用 Thread.currentThread().getContextClassLoader().getResource(""); Thread.currentThread().getContextClassLoader().getResourceAsStream(path); } }
getResource 返回URI, 为资源标识符, 一般都为 file jar 可以使用返回对象的转换方法, 把资源转换为 stream
getResourceAsStream 返回流, 把指定路径的资源转换为流使用
//注意, 如果资源名(path)存在重复, 比如 "/com", 那么请使用 getResources //因为当前 classpath 下还有 jar 包的目录结构是 com 开头的, 使用getResource只返回数组的0下标对象 //如果 path 是相对路径, 则以当前类所在位置, 以相对路径寻找, 如果是绝对路径, 那么从 classpath 向下寻找 Demo.class.getResource(path); Demo.class.getResourceAsStream(path);
//注意, 如果资源名(path)存在重复, 比如 "/com", 那么请使用getResources //因为当前 classpath 下还有 jar 包的目录结构是 com 开头的, 使用getResource只返回数组的0下标对象 //path 必须是相对路径, 且一定从 classpath 为基准向下寻找 Demo.class.getClassLoader().getResource(path); Demo.class.getClassLoader().getResourceAsStream(path); Thread.currentThread().getContextClassLoader().getResource(path); Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
ClassLoader 类调用, 是以类加载器的维度获取资源, 类加载器为 AppClassLoader, 是在当前 classpath 下加载类的, 所以如果以
ClassLoader为维度, 则一定是从 classpath 下寻找
Class 类调用, 实际逻辑和 classLoader 一样, 只不过在开始前, 加了一个函数: resolveName, 处理了绝对路径和相对路径
最终底层和 classLoader 调用的函数一致: getBootstrapResource
个人博客 点击前往