天天看點

Java Review(三十三、異常處理----補充:斷言、日志、調試)使用斷言日志調試技巧

文章目錄

斷言(Assertion)是一種調試程式的方式。在Java中,使用assert關鍵字來實作斷言。

假設确信某個屬性符合要求, 并且代碼的執行依賴于這個屬性。例如, 需要計算:

double y = Math.sqrt(x);      

确信,這裡的 X 是一個非負數值。原因是:X 是另外一個計算的結果,而這個結果不可能是負值;或者 X 是一個方法的參數,而這個方法要求它的調用者隻能提供一個正整數。

當然還應當進行檢查, 以避免讓“ 不是一個數” 的數值參與計算操作。

可以抛出一個異常:

if (x < 0) throw new 111egalArgumentException("x < 0");      

但是這段代碼會一直保留在程式中, 即使測試完畢也不會自動地删除。如果在程式中含有大量的這種檢查,程式運作起來會相當慢。

斷言機制允許在測試期間向代碼中插入一些檢査語句。當代碼釋出時,這些插人的檢測語句将會被自動地移走。

Java 語言引人了關鍵字 assert。這個關鍵字有兩種形式:

assert 條件;      
assert 條件:表達式;      

這兩種形式都會對條件進行檢測, 如果結果為 false, 則抛出一個 AssertionError 異常。

在第二種形式中,表達式将被傳人 AssertionError 的構造器, 并轉換成一個消息字元串。

在預設情況下, 斷言被禁用。可以在運作程式時用 -enableassertions 或 -ea 選項啟用:

java -enableassertions MyApp      

需要注意的是, 在啟用或禁用斷言時不必重新編譯程式。啟用或禁用斷言是類加載器( class loader) 的功能。當斷言被禁用時, 類加載器将跳過斷言代碼, 是以,不會降低程式運作的速度。

也可以在某個類或整個包中使用斷言, 例如:

java -ea:MyClass -eaiconi.inycompany.inylib.. , MyApp      

這條指令将開啟 MyClass 類以及在 com.mycompany.mylib 包和它的子包中的所有類的斷言。選項 -ea 将開啟預設包中的所有類的斷言。

也可以用選項 -disableassertions 或 -da 禁用某個特定類和包的斷言:

ava -ea:... -da:MyClass MyApp      

每個 Java 程式員都很熟悉在有問題的代碼中插入一些 System.out.println 方法調用來幫助觀察程式運作的操作過程。 當然, 一旦發現問題的根源, 就要将這些語句從代碼中删去。如果接下來又出現了問題, 就需要再插入幾個調用 System.out.println方法的語句。

記錄日志API 就是為了解決這個問題而設計的。

下面先讨論這些 API 的優點。

  • 可以很容易地取消全部日志記錄,或者僅僅取消某個級别的日志,而且打開和關閉這個操作也很容易。
  • 可以很簡單地禁止日志記錄的輸出, 是以,将這些日志代碼留在程式中的開銷很小。
  • 日志記錄可以被定向到不同的處理器, 用于在控制台中顯示, 用于存儲在檔案中等。
  • 日志記錄器和處理器都可以對記錄進行過濾。過濾器可以根據過濾實作器制定的标準丢棄那些無用的記錄項。
  • 日志記錄可以采用不同的方式格式化,例如,純文字或 XML。
  • 應用程式可以使用多個日志記錄器, 它們使用類似包名的這種具有層次結構的名字,例如, com.mycompany.myapp0 •在預設情況下,日志系統的配置由配置檔案控制。如果需要的話, 應用程式可以替換

    這個配置。

要生成簡單的日志記錄,可以使用全局日志記錄器(global logger) 并調用其 info 方法:

Logger.getClobal 0,info("File->Open menu item selected");      

在預設情況下,這條記錄将會顯示以下内容:

May 10, 2013 10:12:15 PM LogginglmageViewer fileOpen
INFO: File->0pen menu item selected      

但是, 如果在适當的地方(如 main 開始)調用

Logger.getClobal ().setLevel (Level .OFF);      

将會取消所有的日志。

API: java.util.logging

從前面已經看到“ 虛拟日志”,下面繼續看一下企業級( industrial-strength) 日志。在一個專業的應用程式中,不要将所有的日志都記錄到一個全局日志記錄器中,而是可以自定義日志記錄器。

可以調用 getLogger 方法建立或擷取記錄器:

private static final Logger myLogger = Logger.getLogger("com.mycompany.myapp"):      

與包名類似,日志記錄器名也具有層次結構。事實上, 與包名相比,日志記錄器的層次性更強。 對于包來說,一個包的名字與其父包的名字之間沒有語義關系,但是日志記錄器的父與子之間将共享某些屬性。例如, 如果對 com.mycompany 日志記錄器設定了日志級别,它的子記錄器也會繼承這個級别 。

通常, 有以下 7 個日志記錄器級别:

  • SEVERE
  • WARNING
  • INFO
  • CONFIG
  • FINE
  • FINER
  • FINEST

在預設情況下,隻記錄前夂個級别。 也可以設定其他的級別。例如:

logger,setLevel (Level .FINE);      

現在, FINE 和更進階别的記錄都可以記錄下來。

另外, 還可以使用 Level.ALL 開啟所有級别的記錄, 或者使用 Level.OFF 關閉所有級别的記錄。

對于所有的級别有下面幾種記錄方法:

logger.warning(message):
logger,fine(message) ;      

同時, 還可以使用 log 方法指定級别, 例如:

logger.log(Level .FINE, message);      

日志記錄常用的操作:

  • 1 ) 為一個簡單的應用程式, 選擇一個日志記錄器,并把日志記錄器命名為與主應用程式包一樣的名字,例如,com.mycompany.myprog。

可以通過調用下列方法得到日志記錄器:

Logger logger = Logger.getLogger("com.mycompany.myprog");      

為了友善,可以利用一些日志操作将下面的靜态域添加到類中:

private static final Logger logger = Logger.getLogger("com.mycompany.nyprog"):      
  • 2 ) 預設的日志配置将級别等于或高于 INFO 級别的所有消息記錄到控制台。使用者可以覆寫預設的配置檔案。但是正如前面所述,改變配置需要做相當多的工作。是以,最好在應用程式中安裝一個更加适宜的預設配置。

下列代碼確定将所有的消息記錄到應用程式特定的檔案中。可以将這段代碼放置在應用程式的 main方法中。

if (System,getProperty("java,util.logging.config.dass") == null
&& System.getPropertyC'java.util.logging.config.file") == null) {
try
{
   Logger.getLogger("").setLevel(Level.ALL);
   final int L0C_R0TATI0N_C0UNT = 10;
   Handler handler = new FileHandler('Wmyapp.log", 0, L0G_R0TATI0N_C0UNT):
   Logger.getLogger("").addHandler(handler): }
catch (IOException e) {
  logger.log(Level.SEVERE, "Can't create log file handler", e); 
  }
  }      
  • 3 ) 現在,可以記錄自己想要的内容了。但需要注意:所有級别為 INFO、 WARNING 和SEVERE 的消息都将顯示到控制台上。是以, 最好隻将對程式使用者有意義的消息設定為這幾個級别。将程式員想要的日志記錄,設定為 FINE 是一個很好的選擇。

當調用 System.out.println 時, 實際上生成了下面的日志消息:

logger.fine("File open dialog canceled";      

記錄那些不可預料的異常也,例如:

try
{}
catch (SonreException e) {
   logger,log(Level.FINE, "explanation", e); 
  }      

在Intellij IDEA中使用Debug how2j.java:如何在Eclipse中調試Java程式 W3Cschool:jUnit教程 Spring Boot幹貨系列:(十二)Spring Boot使用單元測試

參考:

【1】:《Java核心技術 卷一》

【2】:

廖雪峰的官方網站:使用斷言

【3】:

廖雪峰的官方網站:使用JDK Logging

【4】:

廖雪峰的官方網站:使用Commons Logging

【5】:

廖雪峰的官方網站:使用Log4j

【6】:

廖雪峰的官方網站:使用SLF4J和Logback

【7】:

how2j.java: Log4j系列教材

繼續閱讀