Class.getResource(String path)
path不以'/'開頭時,默認是從此類所在的包下取資源;path以'/'開頭時,則是從項目的ClassPath根下獲取資源。在這里'/'表示ClassPath
JDK設置這樣的規則,是很好理解的,path不以'/'開頭時,我們就能獲取與當前類所在的路徑相同的資源文件,而以'/'開頭時可以獲取ClassPath根下任意路徑的資源。
如下所示的例子:
運行結果為:
file:/D:/work_space/java/bin/net/swiftlet/
file:/D:/work_space/java/bin/
Class.getClassLoader().getResource(String path)
path不能以'/'開頭時,path是指類加載器的加載范圍,在資源加載的過程中,使用的逐級向上委托的形式加載的,'/'表示Boot ClassLoader中的加載范圍,因為這個類加載器是C++實現的,所以加載范圍為null。如下所示:
運行結果為:
file:/D:/work_space/java/bin/
null
從上面可以看出:
class.getResource("/") == class.getClassLoader().getResource("")
其實,Class.getResource和ClassLoader.getResource本質上是一樣的,都是使用ClassLoader.getResource加載資源的。下面請看一下jdk的Class源碼:
從上面就可以看才出來:Class.getResource和ClassLoader.getResource本質上是一樣的,並且Class.getResource的實現時考慮類加載器為null的情況,直接使用更方便。至於為什么Class.getResource(String path)中path可以'/'開頭,是因為在name = resolveName(name);進行了處理:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
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
;
}
|