1. 程式人生 > >Class.getResource和ClassLoader.getResource的區別分析

Class.getResource和ClassLoader.getResource的區別分析

在Java中獲取資源的時候,經常用到Class.getResource和ClassLoader.getResource,本文給大家說一下這兩者方法在獲取資原始檔的路徑差異。Class.getResource(String path) path不以'/'開頭時,預設是從此類所在的包下取資源;path以'/'開頭時,則是從專案的ClassPath根下獲取資源。在這裡'/'表示ClassPath JDK設定這樣的規則,是很好理解的,path不以'/'開頭時,我們就能獲取與當前類所在的路徑相同的資原始檔,而以'/'開頭時可以獲取ClassPath根下任意路徑的資源。 如下所示的例子:

1

2

3

4

5

6

7

8

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/

Class.getClassLoader().getResource(String path) path不能以'/'開頭時,path是指類載入器的載入範圍,在資源載入的過程中,使用的逐級向上委託的形式載入的,'/'表示Boot ClassLoader中的載入範圍,因為這個類載入器是C++實現的,所以載入範圍為null。如下所示:

1

2

3

4

5

6

7

8

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原始碼:

1

2

3

4

5

6

7

8

9

10

11

  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);進行了處理:

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;

    }