进入Bootstrap类,我们看第一个static{}块,里面有一段代码写法让我有些奇怪,如下:
if (bootstrapJar.exists()) {
File f = new File(userDir, "..");
try {
homeFile = f.getCanonicalFile();
} catch (IOException ioe) {
homeFile = f.getAbsoluteFile();
}
}
为什么要首先调用一次getCanonicalFile,如果不成功再调用一次getAbsoluteFile呢?
一、打开java.io.File源码,看下两个方法的区别
getAbsoluteFile
public File getAbsoluteFile() {
String absPath = getAbsolutePath();
return new File(absPath, fs.prefixLength(absPath));
}getCanonicalFile
public File getCanonicalFile() throws IOException {
String canonPath = getCanonicalPath();
return new File(canonPath, fs.prefixLength(canonPath));
}
通过源码我们可以到getAbsoluteFile是不会抛出异常的,而getCanonicalFile会抛出IOException,两个方法的区别主要体现在所对应的getAbsolutePath方法和getCanonicalPath上。
二、方法getAbsolutePath与getCanonicalPath分析
1. 比对两个方法源码区别
public String getAbsolutePath() {
return fs.resolve(this);
}
public String getCanonicalPath() throws IOException {
if (isInvalid()) {
throw new IOException("Invalid file path");
}
return fs.canonicalize(fs.resolve(this));
}
从代码上看getCanonicalPath比getAbsolutePath多了fs.canonicalize操作,而这个FileSystem类是与操作系统相关的。
2. 从javadoc说明上看
public String getAbsolutePath()
返回此抽象路径名的绝对路径名字符串。
如果此抽象路径名已经是绝对路径名,则返回该路径名字符串,这与 getPath() 方法一样。如果此抽象路径名是空抽象路径名,则返回当前用户目录的路径名字符串,该目录由系统属性 user.dir 指定。否则,使用与系统有关的方式解析此路径名。在 UNIX 系统上,根据当前用户目录解析相对路径名,可使该路径名成为绝对路径名。在 Microsoft Windows 系统上,根据路径名指定的当前驱动器目录(如果有)解析相对路径名,可使该路径名成为绝对路径名;否则,可以根据当前用户目录解析它。
—————————————————————————————————
public String getCanonicalPath() throws IOException
返回此抽象路径名的规范路径名字符串。
规范路径名是绝对路径名,并且是惟一的。规范路径名的准确定义与系统有关。如有必要,此方法首先将路径名转换为绝对路径名,这与调用 getAbsolutePath() 方法的效果一样,然后用与系统相关的方式将它映射到其惟一路径名。这通常涉及到从路径名中移除多余的名称(比如 “.” 和 “..”)、解析符号连接(对于 UNIX 平台),以及将驱动器号转换为标准大小写形式(对于 Microsoft Windows 平台)。
每个表示现存文件或目录的路径名都有一个惟一的规范形式。每个表示不存在文件或目录的路径名也有一个惟一的规范形式。不存在文件或目录路径名的规范形式可能不同于创建文件或目录之后同一路径名的规范形式。同样,现存文件或目录路径名的规范形式可能不同于删除文件或目录之后同一路径名的规范形式。
由此我们可知:getCanonicalPath会将文件路径解析为与操作系统相关的唯一的规范形式的字符串,而getAbsolutePath并不会。
三、测试代码
@Test
public void test01() throws Exception {
File file2 = new File("D:\\JetBrains\\LitterRoach\\javaDevelopworks\\target\\classes\\java.policy");
System.out.println("-----默认绝对路径:取得路径相同------");
System.out.println("getPath: " + file2.getAbsolutePath ());
System.out.println("getCanonicalPath: " + file2.getCanonicalPath());
}
/**
* -----默认绝对路径:取得路径相同------
* getPath: D:\JetBrains\LitterRoach\javaDevelopworks\target\classes\java.policy
* getCanonicalPath: D:\JetBrains\LitterRoach\javaDevelopworks\target\classes\java.policy
*
*/
@Test
public void test02() throws IOException {
//文件存在
System.out.println("=======文件存在=========");
File file1 = new File("./target/classes/JAVA.POLICY");
System.out.println("getPath: " + file1.getAbsolutePath ());
System.out.println("getCanonicalPath: " + file1.getCanonicalPath());
//文件不存在
System.out.println("=======文件不存在=========");
File file2 = new File("JAVA.POLICY");
System.out.println("getPath: " + file2.getAbsolutePath ());
System.out.println("getCanonicalPath: " + file2.getCanonicalPath());
}
/**
* =======文件存在=========
* getPath: D:\JetBrains\LitterRoach\javaDevelopworks\.\target\classes\JAVA.POLICY
* getCanonicalPath: D:\JetBrains\LitterRoach\javaDevelopworks\target\classes\java.policy
* =======文件不存在=========
* getPath: D:\JetBrains\LitterRoach\javaDevelopworks\JAVA.POLICY
* getCanonicalPath: D:\JetBrains\LitterRoach\javaDevelopworks\JAVA.POLICY
*/