Guava學習筆記:Preconditions優雅的檢驗參數(java)
http://www.cnblogs.com/peida/p/guava_preconditions.html
在日常開發中,我們經常會對方法的輸入參數做一些資料格式上的驗證,以便保證方法能夠按照正常流程執行下去。對于可預知的一些資料上的錯誤,我們一定要做事前檢測和判斷,來避免程式流程出錯,而不是完全通過錯誤處理來保證流程正确執行,畢竟錯誤處理是比較消耗資源的方式。在平常情況下我們對參數的判斷都需要自己來逐個寫方法判斷,代碼量不少并且複用性不高,如下所示:


import org.junit.Test;
public class PreconditionsTest {
@Test
public void Preconditions() throws Exception {
getPerson(8,"peida");
getPerson(-9,"peida");
getPerson(8,"");
getPerson(8,null);
}
public static void getPerson(int age,String neme)throws Exception{
if(age>0&&neme!=null&&neme.isEmpty()!=true){
System.out.println("a person age:"+age+",neme:"+neme);
}else{
System.out.println("參數輸入有誤!");
}
}
}


說明:參數驗證,我們每次都要添加if語句來做判斷, 重複的工作會做好多次。getPerson方法隻有2個參數,驗證規則也不是很複雜,如果參數過度,驗證規則複雜後,上面代碼的可讀性都會很差的,複用性就更談不上了。
Guava類庫中提供了一個作參數檢查的工具類--Preconditions類, 該類可以大大地簡化我們代碼中對于參數的預判斷和處理,讓我們對方法輸入參數的驗證實作起來更加簡單優雅,下面我們看看Preconditions類的使用執行個體:


import org.junit.Test;
import com.google.common.base.Preconditions;
public class PreconditionsTest {
@Test
public void Preconditions() throws Exception {
getPersonByPrecondition(8,"peida");
try {
getPersonByPrecondition(-9,"peida");
} catch (Exception e) {
System.out.println(e.getMessage());
}
try {
getPersonByPrecondition(8,"");
} catch (Exception e) {
System.out.println(e.getMessage());
}
try {
getPersonByPrecondition(8,null);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
public static void getPersonByPrecondition(int age,String neme)throws Exception{
Preconditions.checkNotNull(neme, "neme為null");
Preconditions.checkArgument(neme.length()>0, "neme為\'\'");
Preconditions.checkArgument(age>0, "age 必須大于0");
System.out.println("a person age:"+age+",neme:"+neme);
}
}


運作結果:
a person age:8,neme:peida
age 必須大于0
neme為''
neme為null
Preconditions裡面的方法:
1 .checkArgument(boolean) :
功能描述:檢查boolean是否為真。 用作方法中檢查參數
失敗時抛出的異常類型: IllegalArgumentException
2.checkNotNull(T):
功能描述:檢查value不為null, 直接傳回value;
失敗時抛出的異常類型:NullPointerException
3.checkState(boolean):
功能描述:檢查對象的一些狀态,不依賴方法參數。 例如, Iterator可以用來next是否在remove之前被調用。
失敗時抛出的異常類型:IllegalStateException
4.checkElementIndex(int index, int size):
功能描述:檢查index是否為在一個長度為size的list, string或array合法的範圍。 index的範圍區間是[0, size)(包含0不包含size)。無需直接傳入list, string或array, 隻需傳入大小。傳回index。
失敗時抛出的異常類型:IndexOutOfBoundsException
5.checkPositionIndex(int index, int size):
功能描述:檢查位置index是否為在一個長度為size的list, string或array合法的範圍。 index的範圍區間是[0, size)(包含0不包含size)。無需直接傳入list, string或array, 隻需傳入大小。傳回index。
失敗時抛出的異常類型:IndexOutOfBoundsException
6.checkPositionIndexes(int start, int end, int size):
功能描述:檢查[start, end)是一個長度為size的list, string或array合法的範圍子集。伴随着錯誤資訊。
失敗時抛出的異常類型:IndexOutOfBoundsException
一個比較實用執行個體:


import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import com.google.common.base.Preconditions;
public class PreconditionsTest {
@Test
public void Preconditions() throws Exception {
getPersonByPrecondition(8,"peida");
try {
getPersonByPrecondition(-9,"peida");
} catch (Exception e) {
System.out.println(e.getMessage());
}
try {
getPersonByPrecondition(8,"");
} catch (Exception e) {
System.out.println(e.getMessage());
}
try {
getPersonByPrecondition(8,null);
} catch (Exception e) {
System.out.println(e.getMessage());
}
List<Integer> intList=new ArrayList<Integer> ();
for(int i=0;i<10;i++){
try {
checkState(intList,9);
intList.add(i);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
try {
checkPositionIndex(intList,3);
} catch (Exception e) {
System.out.println(e.getMessage());
}
try {
checkPositionIndex(intList,13);
} catch (Exception e) {
System.out.println(e.getMessage());
}
try {
checkPositionIndexes(intList,3,7);
} catch (Exception e) {
System.out.println(e.getMessage());
}
try {
checkPositionIndexes(intList,3,17);
} catch (Exception e) {
System.out.println(e.getMessage());
}
try {
checkPositionIndexes(intList,13,17);
} catch (Exception e) {
System.out.println(e.getMessage());
}
try {
checkElementIndex(intList,6);
} catch (Exception e) {
System.out.println(e.getMessage());
}
try {
checkElementIndex(intList,16);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
public static void getPersonByPrecondition(int age,String neme)throws Exception{
Preconditions.checkNotNull(neme, "neme為null");
Preconditions.checkArgument(neme.length()>0, "neme為\'\'");
Preconditions.checkArgument(age>0, "age 必須大于0");
System.out.println("a person age:"+age+",neme:"+neme);
}
public static void checkState(List<Integer> intList,int index)throws Exception{
//表達式為true不抛異常
Preconditions.checkState(intList.size()<index, " intList size 不能大于"+index);
}
public static void checkPositionIndex(List<Integer> intList,int index) throws Exception{
Preconditions.checkPositionIndex(index, intList.size(), "index "+index+" 不在 list中, List size為:"+intList.size());
}
public static void checkPositionIndexes(List<Integer> intList,int start,int end) throws Exception{
Preconditions.checkPositionIndexes(start, end, intList.size());
}
public static void checkElementIndex(List<Integer> intList,int index) throws Exception{
Preconditions.checkElementIndex(index, intList.size(),"index 為 "+index+" 不在 list中, List size為: "+intList.size());
}
}


輸出結果:


a person age:8,neme:peida
age 必須大于0
neme為''
neme為null
intList size 不能大于9
index 13 不在 list中, List size為:9 (13) must not be greater than size (9)
end index (17) must not be greater than size (9)
start index (13) must not be greater than size (9)
index 為 16 不在 list中, List size為: 9 (16) must be less than size (9)


Guava的preconditions有這樣幾個優點:
在靜态導入後, 方法很明确無歧義, checkNotNull可以清楚地告訴你它是幹什麼的, 它會抛出怎樣的異常.
checkNotNull在驗證通過後直接傳回, 可以這樣友善地寫代碼: this.field = checkNotNull(field).
簡單而又強大的可變參數'printf'風格的自定義錯誤資訊.