1. 前言

在Java中获取资源的时候,经常用到getResource和getResourceAsStream,本文总结一下这两种获取资源文件的路径差异。

2.Class.getResource(String path)

path不以'/'开头时,默认是从此类所在的包下取资源;

path以'/'开头时,则是从项目的ClassPath根下获取资源。在这里'/'表示ClassPath的根目录。

JDK设置这样的规则,是很好理解的,path不以'/'开头时,我们就能获取与当前类所在的路径相同的资源文件,而以'/'开头时可以获取ClassPath根下任意路径的资源。

如下所示的例子:

public class Test
{
public static void main(String[] args)
{
System.out.println(Test.class.getResource(""));
System.out.println(Test.class.getResource("/"));
}
}

运行结果为:
file:/D:/work_space/java/bin/net/swiftlet/
file:/D:/work_space/java/bin/

3.Class.getClassLoader().getResource(String path)
path不能以'/'开头path是指类加载器的加载范围,在资源加载的过程中,使用的逐级向上委托的形式加载的,'/'表示Boot ClassLoader,类加载器中的加载范围,因为这个类加载器是C++实现的,所以加载范围为null。如下所示:

public class Test
{
public static void main(String[] args)
{
System.out.println(Test.class.getClassLoader().getResource(""));
System.out.println(Test.class.getClassLoader().getResource("/"));
}
}

运行结果为:
file:/D:/work_space/java/bin/
null
从上面可以看出:
class.getResource("/") == class.getClassLoader().getResource("")
其实,Class.getResource和ClassLoader.getResource本质上是一样的,都是使用ClassLoader.getResource加载资源的。下面请看一下jdk的Class源码:

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

从上面就可以看才出来:Class.getResource和ClassLoader.getResource本质上是一样的。至于为什么Class.getResource(String path)中path可以'/'开头,是因为在name = resolveName(name);进行了处理:

 private String resolveName(String name)
{
if (name == null)
{
return name;
}
if (!name.startsWith("/"))
{
Class c = this;
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;
}

 4.Class.getResourceAsStream(String path)

path不以'/'开头时,默认是指所在类的相对路径,从这个相对路径下取资源;

path以'/'开头时,则是从项目的ClassPath根下获取资源,就是要写相对于classpath根下的绝对路径。

举例就明白了:

com
|-github
|-demo
| |-A.class
| |-1.txt
|-B.class
|-2.txt
相对路径:InputStream is= A.class.getResourceAsStream("1.txt");
路径不是以/开头,说明这是一个相对路径,相对的是A.class这个文件,所以,这里的“1.txt”所指的正确位置是与A.class处于同一目录下的1.txt文件,这一文件是存在的,所引不会报错。
如果我们按相对路径的方式通过A去加载2.txt,则路径应该这样描述:
InputStream is= A.class.getResourceAsStream("../2.txt");   
是的,用“.."表示上一级目录。
绝对路径:
InputStream is= A.class.getResourceAsStream("/com/github/demo/1.txt");
 5.Class.getResourceAsStream(String path)
Class.getClassLoader.getResourceAsStream(String path) :默认则是从ClassPath根下获取,path不能以’/'开头,最终是由ClassLoader获取资源。
如果以‘/’ 开头,则 返回的是classLoader加载器Boot ClassLoader的加载范围,所以返回的也是null,所以不能以 / 开头。
class.getResourceAsStream最终调用是ClassLoader.getResourceAsStream,这两个方法最终调用还是ClassLoader.getResource()方法加载资源。所以上面的规则也适用于此。
事例:
InputStream resourceAsStream = ClassLoader.getSystemResourceAsStream("com/github/demo/1.txt");
 
转载地址:http://blog.csdn.net/bluishglc/article/details/38753047
http://swiftlet.net/archives/868
 

最新文章

  1. id to load is required for loading
  2. windows的Timer和写文件方式串口注意!
  3. JVM监控与调优
  4. Linux FTP服务器搭建与使用
  5. Thread的第五天学习
  6. Android开发中常用的Eclipse快捷键
  7. 【Deep Learning学习笔记】Dynamic Auto-Encoders for Semantic Indexing_Mirowski_NIPS2010
  8. Codeforces Round #256 (Div. 2/C)/Codeforces448C_Painting Fence(分治)
  9. linux sed命令详解(转)
  10. 续x奇数倍(n+2*x)暴力算法是冠军的算法结合数量
  11. Euclid Problem - PC110703
  12. STL---基本算法---<stl_algobase.h>概述
  13. ZOJ 3923 Handshakes
  14. 多个项目MyEclipse中启动出现OutOfMemoryError: PermGen space如何解决
  15. ABP框架个人开发实战(1)_环境搭建
  16. 《Pro Android Graphics》读书笔记之第六节
  17. iris数据集 决策树实现分类并画出决策树
  18. HTML5特性之AJAX跨域
  19. WinDbg调试 C# dmp
  20. Chapter3_操作符_逻辑操作符

热门文章

  1. 万物智联,腾讯云 IoT 边缘计算揭秘——云+未来峰会开发者专场回顾
  2. Exists/In/Any/All/Contains操作符
  3. svn 不能校验路径“XXX”的锁;没有匹配的可用锁令牌 故障解决方法
  4. JVM(四) G1 收集器工作原理介绍
  5. Python基础学习总结(一)
  6. invalid stream header: EFBFBDEF 问题解决
  7. javaweb之MVC设计模式
  8. dockerfile 踩坑记录
  9. python 需求文件requirements.txt的创建及使用
  10. .net项目常用的库