您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關Java異常處理的技巧有哪些,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
Java異常處理的9個技巧是:
1. 僅在異常情況下使用異常 2. 對可恢復條件使用檢查異常,對編程錯誤使用運行時異常 3. 避免不必要的使用受檢異常 4. 贊成使用標準異常 5. 拋出適合抽象的異常 6. 記錄每個方法拋出的所有異常 7. 在詳細消息中包含故障捕獲信息 8. 力求故障原子性 9. 不要忽視異常
此項主要是避免對普通控制流使用異常。
例如,不是使用異常來終止循環控制流:
try{
Iterator<Foo> iter = ...;
while(true) {
Foo foo = i.next();
...
}
} catch (NoSuchElementException e){
}
應該使用對集合的常規迭代:
for(Iterator<Foo> iter = ...; i.hasNext();){
Foo foo = i.next();
...
}
我沒有找到任何使用常規控制流異常的示例。
大多數情況下,如果調用者可以恢復異常,則應使用已檢查的異常。如果不是,則應使用運行時異常。運行時異常表示可以通過檢查某些先決條件(例如數組邊界和空性檢查)來防止的編程錯誤。
在下面的方法中,IllegalArgumentException
是一個 RuntimeException
,它的用法表示編程錯誤。通常可以通過檢查前提條件來避免編程錯誤。所以這是基于這個技巧的一個不好的例子。可以通過檢查先決條件來避免異常,即這里的“hasNext()
”方法。
/**
* Convert a tag string into a tag map.
*
* @param tagString a space-delimited string of key-value pairs. For example, {@code "key1=value1 key_n=value_n"}
* @return a tag {@link Map}
* @throws IllegalArgumentException if the tag string is corrupted.
*/
public static Map<String, String> parseTags(final String tagString) throws IllegalArgumentException {
// delimit by whitespace or '='
Scanner scanner = new Scanner(tagString).useDelimiter("\\s+|=");
Map<String, String> tagMap = new HashMap<String, String>();
try {
while (scanner.hasNext()) {
String tagName = scanner.next();
String tagValue = scanner.next();
tagMap.put(tagName, tagValue);
}
} catch (NoSuchElementException e) {
// The tag string is corrupted.
throw new IllegalArgumentException("Invalid tag string '" + tagString + "'");
} finally {
scanner.close();
}
return tagMap;
}
檢查異常強制調用者處理異常情況,因為如果沒有,編譯器會抱怨。過度使用檢查異常會給調用者帶來處理異常情況的負擔。所以必要時應該使用受檢異常。使用受檢異常的經驗法則是,當無法通過檢查前提條件避免異常時,調用者可以采取一些有用的操作來處理異常。
常用的運行時異常本身就是不要過度使用檢查異常的例子。在常見的運行時異常有:ArithmeticException
,ClassCastException
異常,拋出:IllegalArgumentException
,IllegalStateException
異常,IndexOutOfBoundExceptions
,NoSuchElementException
異常,和NullPointerException
異常。
在下面的方法中,當propertyName
不是目標情況之一時,調用者可以做的事情不多,因此拋出運行時異常。
@Override
public Object get(String propertyName) {
switch (propertyName.hashCode()) {
case 842855857: // marketDataName
return marketDataName;
case -1169106440: // parameterMetadata
return parameterMetadata;
case 106006350: // order
return order;
case 575402001: // currency
return currency;
case 564403871: // sensitivity
return sensitivity;
default:
throw new NoSuchElementException("Unknown property: " + propertyName);
}
}
最常重用的 Java 異常類如下:
1.java.io.IO異常 2.java.io.FileNotFoundException 3.java.io.UnsupportedEncodingException 4. java.lang.reflect.InvocationTargetException 5.java.security.NoSuchAlgorithmException 6.java.net.MalformedURLException 7.java.text.ParseException 8. java.net.URISyntaxException 9. java.util.concurrent.ExecutionException 10. java.net.UnknownHostException
前 10 名中沒有一個是書中顯示的最常用的。但是要注意,這些是按項目計算的,即如果一個類在一個項目中使用,無論項目中有多少方法在使用它,它都只計算一次。所以這是按項目數計算,但按代碼中出現的次數計算。
拋出的異常應該與調用者執行的任務有聯系。此項介紹異常轉換(捕獲異常并拋出另一個)和異常鏈(將異常包裝在新的異常中以保留異常的因果鏈)。
private void serializeBillingDetails(BillingResult billingResult,
BillingDetailsType billingDetails) {
try {
final JAXBContext context = JAXBContext
.newInstance(BillingdataType.class);
final ByteArrayOutputStream out = new ByteArrayOutputStream();
final Marshaller marshaller = context.createMarshaller();
marshaller.setProperty("jaxb.formatted.output", Boolean.FALSE);
final BillingdataType billingdataType = new BillingdataType();
billingdataType.getBillingDetails().add(billingDetails);
marshaller.marshal(factory.createBillingdata(billingdataType), out);
final String xml = new String(out.toByteArray(), "UTF-8");
billingResult.setResultXML(xml.substring(
xml.indexOf("<Billingdata>") + 13,
xml.indexOf("</Billingdata>")).trim());
billingResult.setGrossAmount(billingDetails.getOverallCosts()
.getGrossAmount());
billingResult.setNetAmount(billingDetails.getOverallCosts()
.getNetAmount());
} catch (JAXBException | UnsupportedEncodingException ex) {
throw new BillingRunFailed(ex);
}
}
上述方法捕獲 JAXBException
和 UnsupportedEncodingException
,并重新拋出一個適合方法抽象級別的新異常。新的 BillingRunFailed
異常包裝了原始異常。所以這是異常鏈的一個很好的例子。異常鏈的好處是保留有助于調試問題的低級異常。
這是嚴重使用不足。大多數公共 API 都沒有 @throws Java 文檔來解釋拋出的異常。
這是一個很好的例子。
...
*
* @throws MalformedURLException The formal system identifier of a
* subordinate catalog cannot be turned into a valid URL.
* @throws IOException Error reading subordinate catalog file.
*/
public String resolveSystem(String systemId)
throws MalformedURLException, IOException {
...
這是一個缺乏有關在什么情況下拋出異常的信息的壞例子。
* @throws Exception exception
*/
public void startServer() throws Exception {
if (!externalDatabaseHost) {
private OutputStream openOutputStream(File file) throws IOException {
if (file.exists()) {
if (file.isDirectory()) {
throw new IOException("File '" + file + "' exists but is a directory");
}
if (!file.canWrite()) {
throw new IOException("File '" + file + "' cannot be written to");
}
} else {
final File parent = file.getParentFile();
if (parent != null) {
if (!parent.mkdirs() && !parent.isDirectory()) {
throw new IOException("Directory '" + parent + "' could not be created");
}
}
}
return new FileOutputStream(file, false);
}
在該方法中,IOException
使用不同的字符串來傳遞不同的故障捕獲信息。
第 8 項是關于失敗的。一般規則是失敗的方法不應該改變方法中對象的狀態。為了盡早失敗,一種方法是在執行操作之前檢查參數的有效性。以下是遵循此提示的一個很好的示例。
/**
* Assigns a new int value to location index of the buffer instance.
* @param index int
* @param newValue int
*/
public void modifyEntry(int index, int newValue) {
if (index < 0 || index > size - 1) {
throw new IndexOutOfBoundsException();
}
// ((int[]) bufferArrayList.get((int) (index / pageSize)))[index % pageSize] =
((int[]) bufferArrayList.get((index >> exp)))[index & r] =
newValue;
}
public static Bundle decodeUrl(String s) {
Bundle params = new Bundle();
if (s != null) {
String array[] = s.split("&");
for (String parameter : array) {
String v[] = parameter.split("=");
try {
params.putString(URLDecoder.decode(v[0], "UTF-8"), URLDecoder.decode(v[1], "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
return params;
}
在生產代碼中幾乎總是應該避免打印堆棧跟蹤。這與忽略異常一樣糟糕。這將寫入標準錯誤流,這不是日志使用日志記錄框架的地方。
關于“Java異常處理的技巧有哪些”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。