Java常見異常處理

異常是Java程序中經(jīng)常遇到的問題,一個(gè)異常就是一個(gè)Bug,就要花很多時(shí)間來定位異常。
Java異常
(1)Throwable是Java異常的頂級類,所有的異常都繼承于這個(gè)類。
(2)Error,Exception是異常類的兩個(gè)大分類。
(3)Error是非程序異常,即程序不能捕獲的異常,一般是編譯或者系統(tǒng)性的錯(cuò)誤,如OutOfMemorry內(nèi)存溢出異常等。
(4)Exception是程序異常類,由程序內(nèi)部產(chǎn)生。Exception又分為運(yùn)行時(shí)異常、非運(yùn)行時(shí)異常。
(5)運(yùn)行時(shí)異常的特點(diǎn)是Java編譯器不會檢查它,也就是說,當(dāng)程序中可能出現(xiàn)這類異常,即使沒有用try-catch語句捕獲它,也沒有用throws子句聲明拋出它,也會編譯通過,運(yùn)行時(shí)異??商幚砘蛘卟惶幚?。運(yùn)行時(shí)異常一般常出來定義系統(tǒng)的自定義異常,業(yè)務(wù)根據(jù)自定義異常做出不同的處理。常見的運(yùn)行時(shí)異常如NullPointException、ArrayIndexOutOfBoundsException等。
(6)非運(yùn)行時(shí)異常是程序必須進(jìn)行處理的異常,捕獲或者拋出,如果不處理程序就不能編譯通過。如常見的IOException、ClassNotFoundException等。
常見的Java異???br/>最頑固的坑--NullPointerException
空指針異常應(yīng)該是每一個(gè)程序員必須要踩得的坑,而且應(yīng)該是經(jīng)常踩不斷踩的坑,極其普遍且難以根除。但是這個(gè)坑可以通過某些方法有效的避免。
(1)什么是空指針?
當(dāng)一個(gè)變量的值為 null 時(shí),在 Java 里面表示一個(gè)不存在的空對象,沒有實(shí)際內(nèi)容,沒有給它分配內(nèi)存,null 也是對象成員變量的默認(rèn)值。
所以,一個(gè)對象如果沒有進(jìn)行初始化操作,這時(shí)候,如果你調(diào)用這個(gè)對象的方法或者變量,就會出現(xiàn)空指針異常。
如下面示例會發(fā)生空指針異常:
Object?object?=?null;
String?string?=?object.toString();
空指針?biāo)菍儆谶\(yùn)行時(shí)異常?RuntimeException?的子類,它不是捕獲型的,只有在程序運(yùn)行時(shí)才可能報(bào)出來,而且會造成程序中斷。
如何有效避免空指針?
以下是我在編碼過程中遇到的問題及解決辦法。
字符串比較,常量放前面---總是從已知的非空String對象中調(diào)用equals()方法
if(status.equals(SUCCESS)){
}
這個(gè)時(shí)候 status 可能為 null 造成空指針異常,應(yīng)該把常量放前面,就能避免空指針異常。這個(gè)應(yīng)該在各種開發(fā)規(guī)范里面都會提到,也是最基礎(chǔ)的。
if(SUCCESS.equals(status)){
}
當(dāng)valueOf()和toString()返回相同的結(jié)果時(shí),寧愿使用前者。
因?yàn)檎{(diào)用null對象的toString()會拋出空指針異常,如果我們能夠使用valueOf()獲得相同的值,那寧愿使用valueOf(),傳遞一個(gè)null給valueOf()將會返回“null”,尤其是在那些包裝類,像Integer、Float、Double和BigDecimal。
BigDecimal bd = getPrice();
System.out.println(String.valueOf(bd));?//不會拋出空指針異常
System.out.println(bd.toString());?//拋出 NullPointerException
初始化默認(rèn)值
在對象初始化的時(shí)候給它一個(gè)默認(rèn)值或者默認(rèn)構(gòu)造實(shí)現(xiàn),如:
User?user?=?new?User();
String?name?=?StringUtils.EMPTY;
避免返回空集合
在返回一個(gè)集合的話,默認(rèn)會是 null,統(tǒng)一規(guī)范返回一個(gè)空集合。
舉個(gè) List 例子,如:
public?List?getUserList(){
????List?list?=?userMapper.gerUserList();
????return?list?==?null???new?ArrayList()?:?list;
}
這樣接收方就不用擔(dān)心空指針異常了,也不會影響業(yè)務(wù)。
采用JDK8 Optional?新特性
?Optional是Jdk8提供的一個(gè)可以包含null值的容器對象,可以用來代替xx != null的判斷。(這個(gè)暫時(shí)因?yàn)槲覀冘嚨老到y(tǒng)統(tǒng)一適用的是Java7,這個(gè)方案還沒有在車到系統(tǒng)代碼里使用過。)
OutOfMemoryError
內(nèi)存異常異常也是一個(gè)經(jīng)常出現(xiàn)的Bug,但是這個(gè)不是程序能控制的,這個(gè)問題是指要分配的對象的內(nèi)存超出了當(dāng)前最大的堆內(nèi)存,需要調(diào)整堆內(nèi)存大?。?Xmx)以及優(yōu)化程序。
(1)常見的有以下幾種原因:
1.內(nèi)存中加載的數(shù)據(jù)量過于龐大,如一次從數(shù)據(jù)庫取出過多數(shù)據(jù);
2.集合類中有對對象的引用使用完后未清空,使得JVM不能回收;
3.代碼中存在死循環(huán)或循環(huán)產(chǎn)生過多重復(fù)的對象實(shí)體;
4.使用的第三方軟件中的BUG;
5.啟動參數(shù)內(nèi)存值設(shè)定的過小
(2)常見解決方法:
1.應(yīng)用服務(wù)器提示錯(cuò)誤的解決:
??把啟動參數(shù)內(nèi)存值設(shè)置足夠大。
2.Java代碼導(dǎo)致錯(cuò)誤的解決:
1)檢查代碼中是否有死循環(huán)或遞歸調(diào)用。
2)檢查是否有大循環(huán)重復(fù)產(chǎn)生新對象實(shí)體。
3)檢查對數(shù)據(jù)庫查詢中,是否有一次獲得全部數(shù)據(jù)的查詢。一般來說,如果一次取十萬條記錄到內(nèi)存,就可能引起內(nèi)存溢出。這個(gè)問題比較隱蔽,在上線前,數(shù)據(jù)庫中數(shù)據(jù)較少,不容易出問題,上線后,數(shù)據(jù)庫中數(shù)據(jù)多了,一次查詢就有可能引起內(nèi)存溢出。因此對于數(shù)據(jù)庫查詢盡量采用分頁的方式查詢。
4 )檢查List、MAP等集合對象是否有使用完后,未清除的問題。List、MAP等集合對象會始終存有對對象的引用,使得這些對象不能被GC回收。
IOException
IO,即:input, output,我們在讀寫磁盤文件、網(wǎng)絡(luò)內(nèi)容的時(shí)候經(jīng)常會生的一種異常,這種異常是受檢查異常,需要進(jìn)行手工捕獲。常用的一種異常處理方式有兩種,一種是:使用throws拋出可能發(fā)生的異常,另一種是:直接try-catch。
ClassNotFoundException
類找不到異常,Java開發(fā)中經(jīng)常遇到,是不是很絕望?這是在加載類的時(shí)候拋出來的,即在類路徑下不能加載指定的類。
注意:在車道程序中不推薦使用throws把異常拋給系統(tǒng)處理,車道系統(tǒng)要捕獲所有能捕獲的異常并進(jìn)行處理,目的是當(dāng)發(fā)生程序級異常時(shí)要保證車道程序可以正常收費(fèi),不可因?yàn)槌绦虍惓S绊懙秸谶M(jìn)行的收費(fèi)處理。
異常處理的一般原則
1、 能處理就早處理,拋出不去還不能處理的異常就要想辦法消化掉,或者轉(zhuǎn)換為RuntimeException處理。因?yàn)閷τ谝粋€(gè)應(yīng)用系統(tǒng)來說,拋出大量異常是有問題的,應(yīng)該從程序開發(fā)角度盡可能的控制異常發(fā)生的可能。
2、 對于檢查異常,如果不能行之有效的處理,還不如轉(zhuǎn)換為RuntimeException拋出。這樣也讓上層的代碼有選擇的余地――可處理也可不處理。
3、 對于一個(gè)應(yīng)用系統(tǒng)來說,應(yīng)該有自己的一套異常處理框架,這樣當(dāng)異常發(fā)生時(shí),也能得到統(tǒng)一的處理風(fēng)格,將優(yōu)雅的異常信息反饋給用戶。
異常的轉(zhuǎn)譯與異常鏈?
?1、異常轉(zhuǎn)譯的原理?
所謂的異常轉(zhuǎn)譯就是將一種異常轉(zhuǎn)換另一種新的異常,也許這種新的異常更能準(zhǔn)確表達(dá)程序發(fā)生異常。
在Java中有個(gè)概念就是異常原因,異常原因?qū)е庐?dāng)前拋出異常的那個(gè)異常對象,幾乎所有帶異常原因的異常構(gòu)造方法都使用Throwable類型做參數(shù),這也就為異常的轉(zhuǎn)譯提供了直接的支持,因?yàn)槿魏涡问降漠惓:湾e(cuò)誤都是Throwable的子類。比如將SQLException轉(zhuǎn)換為另外一個(gè)新的異常DAOException,可以這么寫:
??? 先自定義一個(gè)異常DAOException:
???比如有一個(gè)SQLException類型的異常對象e,要轉(zhuǎn)換為DAOException,可以這么寫:??
public class DAOException extends RuntimeException {
//(省略了部分代碼)
public DAOException(String message, Throwable cause) {
super(message, cause);
}
}
DAOException daoEx = new DAOException ( "SQL異常", e);
異常轉(zhuǎn)譯是針對所有繼承Throwable超類的類而言的,從編程的語法角度講,其子類之間都可以相互轉(zhuǎn)換。但是,從合理性和系統(tǒng)設(shè)計(jì)角度考慮,可將異常分為三類:Error、Exception、RuntimeException。
?異常的處理存在著一套哲學(xué)思想:對于一個(gè)應(yīng)用系統(tǒng)來說,系統(tǒng)所發(fā)生的任何異?;蛘咤e(cuò)誤對操作用戶來說都是系統(tǒng)"運(yùn)行時(shí)"異常,都是這個(gè)應(yīng)用系統(tǒng)內(nèi)部的異常。這也是異常轉(zhuǎn)譯和應(yīng)用系統(tǒng)異??蚣茉O(shè)計(jì)的指導(dǎo)原則。在系統(tǒng)中大量處理非檢查異常的AxiTrader返傭www.fx61.com/brokerlist/axitrader.html負(fù)面影響很多,最重要的一個(gè)方面就是代碼可讀性降低,程序編寫復(fù)雜,異常處理的代碼也很蒼白無力。因此,很有必要將這些檢查異常Exception和錯(cuò)誤Error轉(zhuǎn)換為RuntimeException異常,讓程序員根據(jù)情況來決定是否捕獲和處理所發(fā)生的異常。
①:Error到Exception:將錯(cuò)誤轉(zhuǎn)換為異常,并繼續(xù)拋出。例如Spring WEB框架中,將org.springframework.web.servlet.DispatcherServlet的doDispatch()方法中,將捕獲的錯(cuò)誤轉(zhuǎn)譯為一個(gè)NestedServletException異常。這樣做的目的是為了最大限度挽回因錯(cuò)誤發(fā)生帶來的負(fù)面影響。因?yàn)橐粋€(gè)Error常常是很嚴(yán)重的錯(cuò)誤,可能會引起系統(tǒng)掛起。
②:Exception到RuntimeException:將檢查異常轉(zhuǎn)換為RuntimeException可以讓程序代碼變得更優(yōu)雅,讓開發(fā)人員集中精力設(shè)計(jì)更合理的程序代碼,反過來也增加了系統(tǒng)發(fā)生異常的可能性。
③:Error到RuntimeException:目的還是一樣的。把所有的異常和錯(cuò)誤轉(zhuǎn)譯為不檢查異常,這樣可以讓代碼更為簡潔,還有利于對錯(cuò)誤和異常信息的統(tǒng)一處理。
1、 異常鏈
異常鏈顧名思義就是將異常發(fā)生的原因一個(gè)傳一個(gè)串起來,即把底層的異常信息傳給上層,這樣逐層拋出。Java API文檔中給出了一個(gè)簡單的模型:?
try {
lowLevelOp();
} catch (LowLevelException le) {
throw (HighLevelException)
new HighLevelException().initCause(le);
}
當(dāng)程序捕獲到了一個(gè)底層異常le,在處理部分選擇了繼續(xù)拋出一個(gè)更高級別的新異常給此方法的調(diào)用者。這樣異常的原因就會逐層傳遞。這樣,位于高層的異常遞歸調(diào)用getCause()方法,就可以遍歷各層的異常原因。這就是Java異常鏈的原理。異常鏈的實(shí)際應(yīng)用很少,發(fā)生異常時(shí)候逐層上拋不是個(gè)好注意,上層拿到這些異常又能奈之何?而且異常逐層上拋會消耗大量資源,因?yàn)橐4嬉粋€(gè)完整的異常鏈信息。

10年積累的成都網(wǎng)站制作、成都網(wǎng)站設(shè)計(jì)、外貿(mào)營銷網(wǎng)站建設(shè)經(jīng)驗(yàn),可以快速應(yīng)對客戶對網(wǎng)站的新想法和需求。提供各種問題對應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識你,你也不認(rèn)識我。但先網(wǎng)站設(shè)計(jì)后付款的網(wǎng)站建設(shè)流程,更有紅旗免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。

網(wǎng)站題目:Java常見異常處理
文章位置:http://bm7419.com/article12/iiojdc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供商城網(wǎng)站、ChatGPT微信小程序、品牌網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計(jì)公司、網(wǎng)站排名

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都seo排名網(wǎng)站優(yōu)化