標籤:path java classloader class
java在操作檔案的時候必然需要知道這個檔案在哪裡。每種檔案就是一種資源,java擷取資源的方式有兩種:
1.通過java.io包中的類,例如File,其他類和File類似
2.通過Class或者ClassLoader
先看看File類:
An abstract representation of file and directory pathnames.
User interfaces and operating systems use system-dependent pathname strings to name files and directories. This class presents an abstract, system-independent view of hierarchical pathnames. An abstract pathname has two components:
- An optional system-dependent prefix string, such as a disk-drive specifier,
"/"
for the UNIX root directory, or "\\\\"
for a Microsoft Windows UNC pathname, and
- A sequence of zero or more string names.
官方文檔說File類是檔案和目錄名的一種抽象代表,不依賴於系統,注意理解這句話,在下面的測試代碼中會有所體現
import java.io.File;import java.io.IOException;public class TestResourcePath {public static void main(String[] args) throws IOException {TestResourcePath t = new TestResourcePath();t.testFile();t.testClass();t.testClassLoader();}public void testFile(){File file=new File("dir/1.txt");//注意執行該句,即使這個檔案不存在,這個檔案也不會被建立,只是File類的對象被構造了,這個檔案並不會產生//file.createNewFile();//File無法遞迴的建立檔案及檔案夾System.out.println(file.getAbsolutePath()); File file2=new File("/dir/1.txt");//絕對路徑System.out.println(file2.getAbsolutePath());File file3=new File("1.txt");try {file3.createNewFile();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}//可行System.out.println(file3.getAbsolutePath()); File file4=new File("2.txt");//相對路勁System.out.println(file4.getAbsolutePath());File file5=new File("");System.out.println(file5.getAbsolutePath());File file6=new File("RC/0.gif");System.out.println(file6.getAbsolutePath());File file7=new File("/RC/0.gif");//絕對路勁System.out.println(file7.getAbsolutePath());System.out.println(System.getProperty("user.dir"));System.out.println();}public void testClass(){System.out.println(this.getClass().getResource("RC/0.gif"));System.out.println(this.getClass().getResource("/RC/0.gif"));System.out.println(this.getClass().getResource("1.txt"));System.out.println(this.getClass().getResource("/1.txt"));System.out.println(this.getClass().getResource(""));System.out.println(System.getProperty("java.class.path"));System.out.println();}public void testClassLoader(){System.out.println(this.getClass().getClassLoader().getResource("RC/0.gif"));System.out.println(this.getClass().getClassLoader().getResource("/RC/0.gif"));System.out.println(this.getClass().getClassLoader().getResource("1.txt"));System.out.println(this.getClass().getClassLoader().getResource("/1.txt"));System.out.println(this.getClass().getResource(""));System.out.println(System.getProperty("java.class.path"));System.out.println();}}
下面是列印結果:
E:\Eclipse\javaStudyProjects\Reflect\dir\1.txt
E:\dir\1.txt
E:\Eclipse\javaStudyProjects\Reflect\1.txt
E:\Eclipse\javaStudyProjects\Reflect\2.txt
E:\Eclipse\javaStudyProjects\Reflect
E:\Eclipse\javaStudyProjects\Reflect\RC\0.gif
E:\RC\0.gif
E:\Eclipse\javaStudyProjects\Reflect
這幾個檔案程式執行之前只有0.gif是存在的,執行之後只多了一個E:\Eclipse\javaStudyProjects\Reflect\1.txt;也即是說new File 時,即使這個檔案不存在,這個檔案也不會被建立,只是File類的對象被構造了,這個檔案並不會產生,印證了An abstract representation of file and directory pathnames.File類只是一個抽象代表,並不是正真的檔案,要想這個檔案建立,需要調用createNewFile()方法。如果檔案已存在,createNewFile()方法返回假,不會再次建立。
關於pathname的寫法:
加“/”首碼的表示的是絕對路徑,看file2和file7
不加首碼的是相對路徑,並且這個相對是相對於E:\Eclipse\javaStudyProjects\Reflect\這個路徑,即user.dir
再來看看Class
列印結果:
file:/E:/Eclipse/javaStudyProjects/Reflect/bin/RC/0.gif
file:/E:/Eclipse/javaStudyProjects/Reflect/bin/RC/0.gif
null
null
file:/E:/Eclipse/javaStudyProjects/Reflect/bin/
E:\Eclipse\javaStudyProjects\Reflect\bin
可以看出這個裡面的首碼“/”不在起作用,因為/被過濾掉了,最後的結果都相當於相對路徑,並且這個相對路徑是E:/Eclipse/javaStudyProjects/Reflect/bin/,即java.class.path;也即是當前啟動並執行類所在包的頂層包所在路徑;看看Class.getResource()源碼
public java.net.URL getResource(String name) { name = resolveName(name); ClassLoader cl = getClassLoader(); if (cl==null) { return ClassLoader.getSystemResource(name); // A system class. } return cl.getResource(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;}
在看ClassLoader:
列印結果:
file:/E:/Eclipse/javaStudyProjects/Reflect/bin/RC/0.gif
null
null
null
file:/E:/Eclipse/javaStudyProjects/Reflect/bin/
E:\Eclipse\javaStudyProjects\Reflect\bin
可以看出ClassLoader不處理首碼“/”,所以加/是錯誤的,返回null,其他都和Class一樣,因為Class還是調用了ClassLoader的getResource() 方法
java中的資源路徑resource path