感謝原文作者:不將就!
原文鏈接:https://www.cnblogs.com/byron0918/p/5770684.html
一、getResourceAsStream方法
getResourceAsStream方法實現如下:
public InputStream getResourceAsStream(String name) {
URL url = getResource(name);
try {
return url != null ? url.openStream() : null;
} catch (IOException e) {
return null;
}
}
可見getResourceAsStream方法中調用了getResource方法來查找指定的資源。
再看getResource的源代碼:
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;
}
因為Bootstrap是頂層的classloader,所以java中定義它的parent為null。
此處先判斷parent是不是null,如果parent不是null說明這個class的ClassLoader不是boostrap。
另外通過parent.getResource(name);這一句發現classloader會一直調用它的父類的getResource方法,這和classloader的父類加載機制是一致的。
換句話說,讀取資源文件的時候,目錄的搜索順序是
JRE/lib/rt.jar 注意,搜索的是jar包內的內容,jar包外面的同級目錄不在搜索范圍內
JRE/lib/ext/*.jar
Classpath目錄
而且,如果上級路徑和下級路徑如果同時存在要搜索的資源,那么將以上級路徑下的資源作為搜索結果。
示例:
InputStream in = QuickStart.class.getClassLoader().getResourceAsStream("haha.txt");
InputStreamReader isr = new InputStreamReader(in);
BufferedReader br =new BufferedReader(isr);
String s = null;
while(null != (s = br.readLine())){
System.out.println(s);
}
對於多線程寫法,要用下面的線程上下文的方式讀取:
InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("haha.txt");
補充
-
Thread中的currentThread方法,返回當前正在執行的線程對象。
-
Thread中的getContextClassLoader方法,默認返回調用線程的上下文ClassLoader。
注意:要注意資源獲取時路徑問題!