1. 概述
今天在專案中看到下面兩行代碼,看注釋說是獲取當前作業路徑,之前也沒有用過這種用法,比較好奇還能這樣用,所以研究了一下原始碼,
//獲取當前作業路徑
File file = new File("");
String currentWorkDirectory = file.getAbsolutePath();
2. new File("")決議
首先,new File()是創建一個虛擬的檔案(File)物件,通過這個物件可以呼叫很多方法來獲取檔案和目錄的相關資訊,以下列出一些常用方法:
2.1 File的常用方法
| 方法簽名 | 作用 |
|---|---|
| boolean delete() | 洗掉檔案或目錄 |
| void deleteOnExit() | 在jvm退出時洗掉檔案或目錄 |
| boolean createNewFile() | 當以這個檔案名命名的檔案不存在時,創建一個新的空檔案 |
| boolean exists() | 判斷檔案或目錄是否存在 |
| String getAbsolutePath() | 獲取File物件的絕對路徑 |
| String getName() | 獲取檔案或目錄名稱 |
| File getParentFile() | 獲取父File物件 |
| String getPath() | 獲取File物件創建時傳入的pathname引數 |
| boolean isDirectory() | 判斷是否是目錄 |
| File[] listFiles() | 列出當前目錄下的所有檔案 |
| boolean mkdir() | 創建單個目錄 |
| boolean mkdirs() | 創建多級目錄 |
2.2 new File("")做了什么
我們先來看看原始碼是怎么描述的:

其中注釋的意思是:將指定的檔案路徑轉換為一個絕對路徑,然后創建一個新的File實體,如果給定的檔案路徑引數為空值,則回傳空的絕對路徑名,
官方的注釋比較難理解,通俗的將就是,當我傳入一個相對路徑就會轉換為絕對路徑,當我傳入一個""引數時,就只有一個絕對路徑,那么這個絕對路徑代表什么含義呢?
2.3 深入原始碼看File絕對路徑(abstract pathname)的含義
2.3.1 File.getAbsolutePath()方法
其實我們可以看到new File(String pathname)這個構造方法只設定了相對路徑和決議相對路徑的長度,并沒有有關絕對路徑的操作,那么究竟是在哪里設定的絕對路徑呢?這個就涉及到getAbsolutePath()方法了,
下面我們看一下getAbsolutePath()方法做了什么:

從注釋可以看出,如果在new File()的時候傳入的pathname已經是絕對路徑的話,那么這個方法的回傳就和getPath()一樣,如果傳入的是空字串的話,那么就回傳當前目錄的路徑,通過系統屬性user.dir獲取,
2.3.2 WinNTFileSystem.resolve()方法
那么我們繼續往下看:

點進去resolve()方法可以看到回傳值實際是從getUserPath()這個方法獲取的,

2.3.3 WinNTFileSystem.getUserPath()方法
getUserPath()方法呼叫了System.getProperty("user.dir")方法來獲取user.dir這個key的配置,再往里面看user.dir的值其實是從props這個Properties物件中獲取的,

2.3.4 System.setProperties(props)方法
那props又是從哪里拿到這個值的呢?我們接著往下看:
在System類里面對著props這個屬性用ctrl+滑鼠左鍵查找props在哪幾個地方使用了,可以看到有一個setProperties(Properties props)方法,再對著setProperties這個方法使用ctrl+滑鼠左鍵查找,

2.3.5 Process.main()方法
在com.sun.org.apache.xalan.internal.xslt.Process的main方法里面我們可以看到,執行了System.setProperties(props),而System.setProperties(props)呼叫了本地方法private static native Properties initProperties(Properties props)對props進行初始化,

2.3.6 System.initProperties(Properties props)本地方法

到這里的話,其實java源代碼已經結束了,總結來說就是jvm在啟動的時候呼叫了System類的private static native Properties initProperties(Properties props)本地方法對props屬性進行初始化,設定了user.dir的值,
這時可能還有些好奇寶寶不甘心,為什么呼叫了這個本地方法就可以獲取user.dir的值,那么我們就來研究一下openjdk的c語言原始碼吧,
2.4 深入openjdk原始碼
我們從github上搜索到openjdk的原始碼倉庫,隨便找一個java8的tag來研究initProperties()這個本地方法到底做了什么,
github的openjdk代碼倉庫
-
首先我們找到jdk/src/share/native/java/lang目錄下面的System.c檔案,在里面搜索一下initProperties,可以看到有一個Java_java_lang_System_initProperties方法,

-
接著我們在這個方法里面搜索user_dir,可以看到值是從一個sprops指標中獲取的,而sprops從上一張圖可以看出是從GetJavaProperties(env)這個方法獲取的值,

-
那我們ctrl+shift+F全域搜索一下GetJavaProperties這個方法,可以看到jdk/src/windows/native/java/lang/java_props_md.c檔案中有這個方法,從檔案路徑可以看出這個檔案是windows系統下執行的,

-
接著在這個方法里面搜索user_dir,可以看到user_dir實際是從GetCurrentDirectoryW(sizeof(buf)/sizeof(WCHAR), buf)方法里面獲取值的,GetCurrentDirectoryW這個方法就是windows的系統函式,用來獲取當前作業目錄,

到這里jdk原始碼決議就結束了,可以看到在windows系統下是呼叫了它的系統函式獲取當前作業目錄,
備注:_wcsdup(buf)方法是c語言的庫函式,作用是分配一塊新的空間,然后從buf陣列里面獲取值賦值給新創建的空間,
3. 總結
- 絕對路徑是什么:當前作業目錄,就是當前專案的根路徑
- 使用new File("")創建File物件時,絕對路徑其實是getAbsolutePath()方法獲取的,new File("")只是設定了path=""
- System.props這個屬性其實包含了很多值,如:java.version、user.home等等,可以看原始碼中的注釋
- 通過System.getProperty(key)可以獲取系統的一些配置資訊
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/502633.html
標籤:其他
上一篇:OpenGL 波浪特效
