CoreJava讀書筆記--異常、斷言和日誌(二)--斷言和日誌
使用斷言
在一個具有自我保護能力的程式中,斷言很常用。
(一)斷言的概念
斷言機制允許在測試期間向程式碼中插入一些檢查語句。當代碼釋出時,這些插入的檢測語句將會被自動地移走。Java語言引入了關鍵字assert。assert有兩種形式:
assert 條件;
和
assert 條件 : 表示式;
這兩種形式都會對條件進行檢測,如果結果為false,則丟擲一個AssertionError異常。在第二種形式中,表示式將被傳入AssertionError構造器,並轉換成一個訊息字串。表示式部分的唯一目的是產生一個訊息字串。例如:需要計算
double y = Math.sqrt(x);
我們知道x不能為負數,要想使用斷言,只需要簡單地使用assert語句,進行測試即可:
assert x>=0;
或者將x的實際值傳遞給AssertionError物件,從而可以在後面顯示出來。
assert x>=0 : x;
(二)啟用和禁用斷言
在預設情況下,斷言被禁用。可以在執行程式時用-enableassertions或-ea選項啟用:
java -enableassertions MyApp
需要注意的是,在啟用或禁用斷言時不必重新編譯程式。啟用或禁用斷言是類載入器(class loader)的功能。當斷言被禁用時,類載入器將跳過斷言程式碼,因此,不會降低程式執行的速度。
也可以在某個類或整個包中使用斷言,例如:
java -ea:MyClass //斷言某個類
java -ea:com.mycompany.mylib...MyApp //斷言某個包
//系統類不是由類載入器載入,所以不能用-ea 和-da,而是使用下面開關啟用斷言
-enablesystemassertions/-esa
也可以使用選項-disableassertions或-da禁用某個特定類和包的斷言:
-da:MyClass MyApp
-disableassertions:MyClass
(三)使用斷言完成引數檢查
在Java語言中,給出了3種處理系統錯誤的機制:
- 丟擲一個異常
- 日誌
- 使用斷言
什麼時候應該選擇使用斷言呢?
- 斷言失敗是致命的、不可恢復的錯誤
- 斷言檢查只用於開發和測試階段
注意:①不要在public方法裡面檢查引數是不是為null之類的操作
②不要用assert來檢查方法操作的返回值來判斷方法操作的結果
日誌
我們總是用System.out.println方法呼叫來幫助觀察程式執行的操作過程,但是太過複雜,記錄日誌API就是為了解決這個問題而設計的。下面看看記錄日誌API的優點:
①可以很容易的取消全部日誌記錄,或者僅僅取消某個級別的日誌,而且開啟和關閉這個操作也容易
②可以很簡單的禁止日誌記錄的輸出,因此,將這些日誌程式碼留在程式中的開銷很小
③日誌可以被定向到不同的處理器,例如用於在控制檯顯示,用於儲存在檔案中
④日誌記錄器和處理器都可以對記錄進行過濾,過濾器也可以根據實際制定過濾標準,丟棄那些無用的記錄項
⑤日誌記錄可以採用不同的方式格式化,例如:純文字或XML
⑥應用程式可以使用多個日誌記錄器,它們使用類似包名的這種具有層次結構的名字
⑦在預設情況下,日誌系統的配置由配置檔案控制
(一)基本日誌
要生成簡單的日誌記錄,可以使用全域性日誌記錄器(global logger)並呼叫其info方法:
Logger.getGlobal().info("File->Open menu item selected");
也可以在適當地方呼叫關閉全域性記錄器的方法:
Logger.getGlobal().setLevel(Level.OFF);
將會取消所有的日誌。
(二)高階日誌
在一個專業的應用程式中,不要將所有的日誌都記錄到一個全域性日誌記錄器中,而是可以自定義日誌記錄器。可以呼叫getLogger方法建立或獲取記錄器:
private static final Logger myLogger = Logger.getLogger("com.company.myapp");
提示:未被任何變數引用的日誌記錄器可能會被垃圾回收。為了防止這種情況發生,要像上面的例子中一樣,用一個靜態變數儲存日誌記錄器的一個引用。
與包名類似,日誌記錄器名也具有層次結構。事實上,日誌記錄器也有級別,通常,有以下7個日誌記錄器級別:
- SEVERE
- WARNING
- INFO
- CONFIG
- FINE
- FINER
- FINEST
在預設情況下,只記錄前三個級別,也可以設定其他的級別。例如:
logger.setLevel(Level.FINE);
現在,FINE和更高級別的記錄都可以記錄下來。另外,也可以使用Level.ALL開啟所有級別的記錄,或者使用Level.OFF關閉所有級別的記錄。
預設的日誌記錄將顯示包含日誌呼叫的類名和方法名,如同堆疊所顯示的那樣。但是,如果虛擬機器對執行過程進行了優化,就得不到準確的呼叫資訊。此時,可以呼叫logp方法獲得呼叫類和方法的確切位置,這個方法的簽名為:
void logp(Level lev,String className,String methodName,String message)
(三)修改日誌管理器配置
可以通過編輯配置檔案來修改日誌系統的各種屬性。在預設情況下,配置檔案存在於:
jre/lib/logging.properties
要想使用另一個配置檔案,就要將java.util.logging.config.file特性設定為配置檔案的儲存位置,並用下列命令啟動應用程式:
java -Djava.util.logging.config.file=configFile MainClass
要想修改預設的日誌記錄級別,就需要編輯配置檔案,並修改以下命令列
.level = INFO
可以通過新增以下內容來指定自己的日誌記錄級別
com.mycompany.myapp.level=FINE
之後可以看到,我們這麼設定是不能在控制檯上看到日誌記錄的,這是處理器的任務。另外,處理器也有級別。要想在控制檯上看到FINE級別的訊息,就需要進行下列設定:
java.util.logging.ConsoleHandler.level=FINE
(四)日誌記錄說明
①為一個簡單的應用程式,選擇一個日誌記錄器,並把日誌記錄器命名為與主應用程式包一樣的名字。
②預設的日誌配置將級別等於或高於INFO級別的所有訊息記錄到控制檯上。
③所有級別為INFO、WARNING、SEVERE的訊息都將顯示到控制檯上。因此,最好只將對程式使用者有意義的訊息設定為這幾個級別。