我們平時在寫代碼的時候經常會遇到這樣的一種情況
提示說沒有處理xxx異常
然后解決辦法可以在外面加上try-catch,就像這樣
所以我之前經常這樣處理
//重新拋出 RuntimeException
public class ThrowsDemo {
public void demo4throws() {
try {
new ThrowsSample().sample4throws();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
//打印日志
@Slf4j
public class ThrowsDemo {
public void demo4throws() {
try {
new ThrowsSample().sample4throws();
} catch (IOException e) {
log.error("sample4throws", e);
}
}
}
//繼續往外拋,但是需要每個方法都添加 throws
public class ThrowsDemo {
public void demo4throws() throws IOException {
new ThrowsSample().sample4throws();
}
}
但是我一直不明白
這個方法為什么不直接幫我做
反而要讓我很多余的加上一步
我處理和它處理有什么區別嗎?
而且變的好不美觀
本來縮進就多,現在加個try-catch更是火上澆油
public class ThrowsDemo {
public void demo4throws() {
try {
if (xxx) {
try {
if (yyy) {
} else {
}
} catch (Throwable e) {
}
} else {
}
} catch (IOException e) {
}
}
}
上面的代碼,就算里面沒有業務,看起來也已經比較亂了,分不清哪個括號和哪個括號是一對
還有就是對Lambda很不友好
沒有辦法直接用::來優化代碼,所以就變成了下面這樣
本來看起來很簡單很舒服的Lambda,現在又變得又臭又長
為什么會強制 try-catch
為什么我們平時寫的方法不需要強制try-catch,而很多jdk中的方法卻要呢
那是因為那些方法在方法的定義上添加了throws關鍵字,并且后面跟的異常不是RuntimeException
一旦你顯式的添加了這個關鍵字在方法上,同時后面跟的異常不是RuntimeException,那么使用這個方法的時候就必須要顯示的處理
比如使用try-catch或者是給調用這個方法的方法也添加throws以及對應的異常
throws 是用來干什么的
那么為什么要給方法添加throws關鍵字呢?
給方法添加throws關鍵字是為了表明這個方法可能會拋出哪些異常
就像一個風險告知
這樣你在看到這個方法的定義的時候就一目了然了:這個方法可能會出現什么異常
為什么 RuntimeException 不強制 try-catch
那為什么RuntimeException不強制try-catch呢?
因為很多的RuntimeException都是因為程序的BUG而產生的
比如我們調用Integer.parseInt("A")會拋出NumberFormatException
當我們的代碼中出現了這個異常,那么我們就需要修復這個異常
當我們修復了這個異常之后,就不會再拋出這個異常了,所以try-catch就沒有必要了
當然像下面這種代碼除外
public boolean isInteger(String s) {
try {
Integer.parseInt(s);
return true;
} catch (NumberFormatException e) {
return false;
}
}
這是我們利用這個異常來達成我們的需求,是有意為之的
而另外一些異常是屬于沒辦法用代碼解決的異常,比如IOException
我們在進行網絡請求的時候就有可能拋出這類異常
因為網絡可能會出現不穩定的情況,而我們對這個情況是無法干預的
所以我們需要提前考慮各種突發情況
強制try-catch相當于間接的保證了程序的健壯性
畢竟我們平時寫代碼,如果IDE沒有提示異常處理,我們完全不會認為這個方法會拋出異常
我的代碼怎么可能有問題!
看來JAVA之父完全預判到了程序員的腦回路
throws 和 throw 的區別
java中還有一個關鍵詞throw,和throws只有一個s的差別
throw是用來主動拋出一個異常
public class ThrowsDemo {
public void demo4throws() throws RuntimeException {
throw new RuntimeException();
}
}
兩者完全是不同的功能,大家不要弄錯了
什么場景用 throws
我們可以發現我們平時寫代碼的時候其實很少使用throws
因為當我們在開發業務的時候,所有的分支都已經確定了
比如網絡請求出現異常的時候,我們常用的方式可能是打印日志,或是進行重試,把異常往外拋等等
所以我們沒有那么有必要去使用throws這個關鍵字來說明異常信息
但是當我們沒有辦法確定異常要怎么處理的時候呢?
比如我在GitHub上維護了一個功能庫,本身沒有什么業務屬性,主要就是對于一些復雜的功能做了相應的封裝,提供給自己或別人使用
對我來說,當我的方法中出現異常時,我是不清楚調用這個方法的人是想要怎么處理的
可能有的想要重試,有的想要打印日志,那么我干脆就往外拋,讓調用方法的人自己去考慮,自己去處理
所以簡單來說,如果方法主要是給別人用的最好用throws把異常往外拋,反之就是可加可不加
結束
很多時候你的不理解只是因為你還不夠了解