电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術(shù)文章
文章詳情頁

Java中Exception和Error的區(qū)別詳解

瀏覽:55日期:2022-08-09 11:12:49

世界上存在永遠(yuǎn)不會出錯的程序嗎?也許這只會出現(xiàn)在程序員的夢中。隨著編程語言和軟件的誕生,異常情況就如影隨形地糾纏著我們,只有正確的處理好意外情況,才能保證程序的可靠性。 java語言在設(shè)計之初就提供了相對完善的異常處理機(jī)制,這也是java得以大行其道的原因之一,因為這種機(jī)制大大降低了編寫和維護(hù)可靠程序的門檻。如今,異常處理機(jī)制已經(jīng)成為現(xiàn)代編程語言的標(biāo)配。 今天我要問你的問題是,請對比Exception和Error,另外,運(yùn)行時異常與一般異常有什么區(qū)別? 典型回答Exception和Error都是繼承了Throwable類,在java中只有Throwable類型的實(shí)例才可以被拋出(throw)或者捕獲(catch),他是異常處理機(jī)制的基本組成類型。 Exception和Error體現(xiàn)了java平臺設(shè)計者對不同異常情況的分類,Exception是程序正常運(yùn)行中,可以預(yù)料的意外情況,可能并且應(yīng)該被捕獲,進(jìn)行相應(yīng)的處理。 Error是指正常情況下,不大可能出現(xiàn)的情況,絕大部分的Error都會導(dǎo)致程序(比如JVM自身)處于非正常狀態(tài),不可恢復(fù)狀態(tài)。既然是非正常情況,所以不便于也不需要捕獲,常見的比如OutOfMemoryError之類,都是Error的子類。 Exception又分為可檢查(checked)異常和不檢查(unchecked)異常,可檢查異常在源碼里必須顯示的進(jìn)行捕獲處理,這里是編譯期檢查的一部分。前面我們介紹的不可查的Error,是Throwable不是Exception。 不檢查異常就是所謂的運(yùn)行時異常,類似NullPointerException,ArrayIndexOutOfBoundsExceptin之類,通常是可以編碼避免的邏輯錯誤,具體根據(jù)需要來判斷是否需要捕獲,并不會在編譯器強(qiáng)制要求。

考點(diǎn)分析: 分析Exception和Error的區(qū)別,是從概念角度考察了java處理機(jī)制。總的來說,還處于理解的層面,面試者只要闡述清楚就好了。 我們在日常的編程中,如何處理好異常是比較考驗功底的。我覺得需要掌握兩個方面: 第一,理解Throwable,Exception,Error的設(shè)計和分類。比如,掌握那些應(yīng)用最為廣泛的子類,以及如何自定義異常等。 很多面試官會進(jìn)一步追問一些細(xì)節(jié),比如,你了解哪些Error,Exception或者RuntimeException?我畫了一個簡單的類圖,并列出來典型例子,可以給你作為參考,至少做到基本心里有數(shù)。

Java中Exception和Error的區(qū)別詳解

其中有些子類型,最好重點(diǎn)理解一下,比如 NoClassDefFoundError和ClassNotFoundException有什么區(qū)別,這也是一個經(jīng)典的入門題目。 簡單總結(jié)就是,NoClassDefFoundError發(fā)生在編譯時對應(yīng)的類可用,而運(yùn)行時在Java的classpath路徑中,對應(yīng)的類不可用導(dǎo)致的錯誤。 第二,理解java語言中操作Throwable的元素和實(shí)踐。掌握最基本的語法是必須的,比如try-catch-finally塊,throw,throws關(guān)鍵字等。與此同時,也要懂得如何處理典型場景。 異常處理代碼比較繁瑣,比如我們需要寫很多千篇一律的捕獲代碼,或者在finally里面做一些資源回收工作。隨著java語言的發(fā)展,引入了一些更加便利的特性,比如try-with-resource和multiple catch,具體可以參考小面的代碼段,在編譯時期,會自動生成相應(yīng)的處理邏輯,比如,自動按照約定俗成close那些擴(kuò)展了AutoCloseable或者Closeable的對象。

try(BuffereReader br =new BufferReader(...); BufferedWriter writer = new BufferredWriter(...)) {//dosomething}catch(IOException | XException){//handle it}

知識擴(kuò)展 前面談的大多是概念性的東西,下面我來談一些實(shí)踐中的選擇,我會結(jié)合一些代碼用例進(jìn)行分析。 先看第一個,下面的代碼反應(yīng)了異常處理中哪些不當(dāng)之處?

try{//業(yè)務(wù)代碼Thread.sleep(1000L);}catch(Exception e){//Ignore it}

這段代碼雖然很短,但是異常違反了異常處理的兩個基本原則。 第一,盡量不要捕獲類似Exception這樣的通用異常,而是應(yīng)該捕獲特定異常,這里是Thread。sleep()拋出的InterruptedException. 這是因為在日常的開發(fā)合作中,我們讀代碼的機(jī)會往往超過寫代碼,軟件工程師門協(xié)作的藝術(shù),所以我們有義務(wù)讓自己的代碼能夠直觀體現(xiàn)出盡多的信息,而泛泛的Exception之類,恰恰隱藏了我們的目的。另外。我們也要保證程序不會捕捉到我們不希望捕獲的異常。比如你可能更希望RuntimeException被擴(kuò)散出來,而不是被捕獲。 進(jìn)一步講,除非深思熟慮了,否者不要捕獲Throwable或者Error,這樣很難保證我們能夠正確程序處理OutOfMemoryError. 第二,不要生吞(swallow)異常。這一異常處理中特別注意的事情,很可能會導(dǎo)致非常難以診斷的詭異情況。 生吞異常,往往是基于假設(shè)這段代碼可能不會發(fā)生,或者感覺忽略異常是無所謂的,但是千萬不要在產(chǎn)品代碼做這種假設(shè)! 如果我們不能把異常拋出來,或者也沒有輸出到日志(Logger)之類,程序可能會在后續(xù)代碼以不可控的方式結(jié)束。沒人能夠輕易判斷究竟是哪里拋出了異常,以及什么原因產(chǎn)生了異常。 再看第二段代碼

try{//業(yè)務(wù)代碼}catch(IOException e){ e.printStackTrace();}

這段代碼作為一段實(shí)驗代碼,他沒有任何問題,但是在產(chǎn)品代碼中,通常是不允許這樣處理的。你先考慮一下為什么? 我們先來看一下printStackTrace()的文檔,開頭就是Prints this throwable and its backtrace to the standard error stream問題就在這里,在稍微復(fù)雜一點(diǎn)的生產(chǎn)系統(tǒng)中,標(biāo)準(zhǔn)出錯(STERR)不是個合適的輸出選項,因為你很難判斷出到底輸出到哪里去了。 尤其是分布式系統(tǒng),如果發(fā)生異常,但是無法找到堆棧軌跡(stacktrace),這純屬是為診斷設(shè)置障礙,所以最好使用產(chǎn)品日志,詳細(xì)地輸出到日志系統(tǒng)里。 我們接下來看下面的代碼段,體會一下Throw early,catch late原則。

public void readPreferences(String fileName){ //perform operations... InputStream in = new FileInputStream(fileName); //..read the preferences file...}

如果fileName是null,那么程序就會拋出NullPointerException,但是由于沒有第一時間暴露出問題,堆棧信息可能非常令人費(fèi)解,往往需要相對復(fù)雜的定位。這個NPE只是作為例子,實(shí)際產(chǎn)品代碼中,可能是各種情況,比如獲取配置失敗之類的。在發(fā)現(xiàn)問題的時候,第一時間拋出,能夠更加清晰地反映問題。 我們可以修改一下,讓問題throw early ,對應(yīng)的異常信息就會非常直觀了。

public void readPreferences(String fileName){ Objects.requireNonNull(fileName); //perform operations... InputStream in = new FileInputStream(fileName); //..read the preferences file...

至于catch late ,其實(shí)是我們經(jīng)常苦惱的問題,捕獲異常后,需要怎么處理呢?最差的處理方式,就是我們前面提到的“生吞異常”,本質(zhì)上其實(shí)是掩蓋問題。如果實(shí)在不知道怎么處理,可以選擇保留原有異常的cause信息,直接再拋出或者構(gòu)建新的異常拋出。在更高層面,因為有了清晰的(業(yè)務(wù))邏輯,往往會更清楚合適的處理方式是什么。

有的時候我們會更具需要自定義異常,這個時候除了保證提供足夠的信息,還有兩個點(diǎn)需要考慮:

是否需要定義成Checked Exception,因為這種類型設(shè)計的初衷就是為了從異常情況下恢復(fù),作為異常設(shè)計者,我們往往有充足信息進(jìn)行分類。 為保證診斷信息足夠的同時,要考慮避免包含敏感信息,因為那樣可能導(dǎo)致潛在的安全問題。如果我們看java的標(biāo)準(zhǔn)庫,你可能注意到類似java.net.ConnectException,出錯信息是類似“connection refused(connection refused)”,而不包含具體的機(jī)器名,ip,端口等,一個重要考慮就是信息安全。類似的情況在日志中也有,比如,用戶數(shù)據(jù)一般是不可以輸出到日志里面的。 業(yè)界有一種爭論(甚至可以算上是某種程度的共識),java語言的checked Exception也許是個設(shè)計錯誤,反對者列舉幾點(diǎn): checked Exception的假設(shè)是我們捕獲了異常,然后恢復(fù)程序。但是,其實(shí)我們大多數(shù)情況下,根本不可能恢復(fù)。checked exception的使用,已經(jīng)大大偏離了最初的設(shè)計目的。 checked Exception不兼容functional編程,如果你寫過lambda/stream代碼,相信深有體會。 很多開源項目,已經(jīng)采納了這種實(shí)踐,比如spring,hibernate等,甚至反映在新的編程語言的設(shè)計中,比如Scala等。 當(dāng)然,很多人覺得沒有必要矯枉過正,因為確實(shí)有一些異常,比如和環(huán)境相關(guān)的IO,網(wǎng)絡(luò)等,其實(shí)是存在可回復(fù)性的,而且java已經(jīng)通過業(yè)界的海量實(shí)踐,證明了其結(jié)構(gòu)高質(zhì)量軟件的能力。我們就不再進(jìn)一步解讀了。 我們從性能角度來審視一下java的異常處理機(jī)制,這里有兩個可能會相對昂貴的地方: try-catch代碼段會產(chǎn)生額外的性能開銷,或者換個角度說,他往往會影響JVM對代碼進(jìn)行優(yōu)化,所以建議僅捕獲有必要的代碼段,盡量不要一個大的try包住整段的代碼;與此同時,利用異常控制代碼流程,也不是一個好主意,遠(yuǎn)比我們通常意義上的條件語句(if/else,switch)要低效 java每實(shí)例化一個Exception,都會對當(dāng)時的棧進(jìn)行快照,這是一個相對比較重的操作。如果發(fā)生的非常的頻繁,這個開銷可能就不能被忽略了。 所以,對于部分追求極致性能的底層類庫,有種方式是嘗試創(chuàng)建不進(jìn)行快照的Exception.這本身也存在爭議,因為這樣做的假設(shè)在于,我創(chuàng)建異常時知道未來是否需要堆棧。問題是實(shí)際上可能嗎?小范圍或許可能,但是在大規(guī)模項目中,這么做可能不是個理智的選擇。如果需要堆棧,但是沒有收集這些信息,在復(fù)雜情況下,尤其是類似微服務(wù)這種分布式系統(tǒng),這會大大增加診斷的難度。 當(dāng)我們的服務(wù)出現(xiàn)反應(yīng)慢,吞吐量下降的時候,檢查發(fā)生最頻繁的Exception也是一種思路。關(guān)于診斷后臺變慢的問題,我們會在后面的java性能基礎(chǔ)模塊中系統(tǒng)討論。 今天,我從一個常見的異常處理概念問題,簡單的總結(jié)了java異常處理機(jī)制,并結(jié)合代碼,分析了一些普遍認(rèn)可的最佳實(shí)踐,以及業(yè)界最新的一些異常使用共識。最后,我分析了一下異常開銷,希望能對你有所幫助。 一課一練 關(guān)于我們討論的題目你做到心中有數(shù)了嗎?可以思考一個問題,對于異常處理編程,不同的編程范式也會影響到異常的處理策略,比如,現(xiàn)在非常火熱的反應(yīng)式編程,因為其本身是異步,基于事件機(jī)制的,所以出現(xiàn)異常情況,決不能簡單的拋出;另外,由于代碼堆棧不再是同步調(diào)用那種垂直結(jié)構(gòu),這里的異常處理和日志需要更加小心,我們看到的往往是特定executor的堆棧,而不是業(yè)務(wù)方法調(diào)用關(guān)系,對于這種情況,你有什么好的辦法嗎?

到此這篇關(guān)于Java中Exception和Error的區(qū)別詳解的文章就介紹到這了,更多相關(guān)Java Exception和Error區(qū)別內(nèi)容請搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Java
相關(guān)文章:
主站蜘蛛池模板: 制冷采购电子商务平台——制冷大市场 | 液压扳手-高品质液压扳手供应商 - 液压扳手, 液压扳手供应商, 德国进口液压拉马 | 深圳富泰鑫五金_五金冲压件加工_五金配件加工_精密零件加工厂 | 百度网站优化,关键词排名,SEO优化-搜索引擎营销推广 | 四川职高信息网-初高中、大专、职业技术学校招生信息网 | 超声波分散机-均质机-萃取仪-超声波涂料分散设备-杭州精浩 | 专业音响设备_舞台音响设备_会议音响工程-首选深圳一禾科技 | 桨叶搅拌机_螺旋挤压/方盒旋切造粒机厂家-无锡市鸿诚输送机械有限公司 | 蓝牙音频分析仪-多功能-四通道-八通道音频分析仪-东莞市奥普新音频技术有限公司 | 对辊破碎机_四辊破碎机_双齿辊破碎机_华盛铭重工| 播音主持培训-中影人教育播音主持学苑「官网」-中国艺考界的贵族学校 | 泰国试管婴儿_泰国第三代试管婴儿_泰国试管婴儿费用/多少钱_孕泰来 | 27PR跨境电商导航 | 专注外贸跨境电商 | 全国国际化学校_国际高中招生_一站式升学择校服务-国际学校网 | 润滑油加盟_润滑油厂家_润滑油品牌-深圳市沃丹润滑科技有限公司 琉璃瓦-琉璃瓦厂家-安徽盛阳新型建材科技有限公司 | 消防泵-XBD单级卧式/立式消防泵-上海塑泉泵阀(集团)有限公司 | 拖链电缆_柔性电缆_伺服电缆_坦克链电缆-深圳市顺电工业电缆有限公司 | 防爆暖风机_防爆电暖器_防爆电暖风机_防爆电热油汀_南阳市中通智能科技集团有限公司 | 蓝米云-专注于高性价比香港/美国VPS云服务器及海外公益型免费虚拟主机 | 免费分销系统 — 分销商城系统_分销小程序开发 -【微商来】 | 无尘烘箱_洁净烤箱_真空无氧烤箱_半导体烤箱_电子防潮柜-深圳市怡和兴机电 | 清水混凝土修复_混凝土色差修复剂_混凝土色差调整剂_清水混凝土色差修复_河南天工 | 焦作网 WWW.JZRB.COM| 仿清水混凝土_清水混凝土装修_施工_修饰_保护剂_修补_清水混凝土修复-德州忠岭建筑装饰工程 | 洗地机_全自动洗地机_手推式洗地机【上海滢皓环保】 | 展厅设计公司,展厅公司,展厅设计,展厅施工,展厅装修,企业展厅,展馆设计公司-深圳广州展厅设计公司 | 石油/泥浆/不锈钢防腐/砂泵/抽砂泵/砂砾泵/吸砂泵/压滤机泵 - 专业石油环保专用泵厂家 | 全球化工设备网—化工设备,化工机械,制药设备,环保设备的专业网络市场。 | 丹尼克尔拧紧枪_自动送钉机_智能电批_柔性振动盘_螺丝供料器品牌 | 环氧树脂地坪漆_济宁市新天地漆业有限公司 | 仿古瓦,仿古金属瓦,铝瓦,铜瓦,铝合金瓦-西安东申景观艺术工程有限公司 | 二手电脑回收_二手打印机回收_二手复印机回_硒鼓墨盒回收-广州益美二手电脑回收公司 | 英国雷迪地下管线探测仪-雷迪RD8100管线仪-多功能数字听漏仪-北京迪瑞进创科技有限公司 | SDI车窗夹力测试仪-KEMKRAFT方向盘测试仪-上海爱泽工业设备有限公司 | 电缆故障测试仪_电缆故障定位仪_探测仪_检测仪器_陕西意联电气厂家 | 压缩空气冷冻式干燥机_吸附式干燥机_吸干机_沪盛冷干机 | 讲师宝经纪-专业培训机构师资供应商_培训机构找讲师、培训师、讲师经纪就上讲师宝经纪 | 【连江县榕彩涂料有限公司】官方网站 | 软文世界-软文推广-软文营销-新闻稿发布-一站式软文自助发稿平台 | 注浆压力变送器-高温熔体传感器-矿用压力传感器|ZHYQ朝辉 | 皮带机_移动皮带机_大倾角皮带机_皮带机厂家 - 新乡市国盛机械设备有限公司 |