? ? ? ?這一篇內(nèi)容比較長浮毯,超過限制了,另附一小段断医,接上篇滞乙。
????09-面向?qū)ο?自定義異常)
? ? ? ? 因?yàn)轫?xiàng)目中會(huì)出現(xiàn)特有的問題奏纪,而這些問題并未被Java所描述并封裝對象。
????所以斩启,對于這些特有的問題可以按照J(rèn)ava的對問題封裝的思想序调,將特有的問題,進(jìn)行自定義的異常封裝兔簇。這就是自定義異常发绢。
? ? ? ? 還是以剛剛的程序?yàn)槔?/p>
? ? ? ? 現(xiàn)在自己封裝一個(gè)異常,注意命名方式都是按規(guī)范的來的哦:
? ? ? ? 先不用給里面寫什么垄琐,我們現(xiàn)在建立它的目的只是為了生成對象边酒。
? ? ? ? 我們自定義的異常,Java不認(rèn)識(shí)狸窘,這個(gè)時(shí)候就需要我們手動(dòng)建立對象墩朦,并進(jìn)行拋出。(之前都是自動(dòng)拋出翻擒,現(xiàn)在是手動(dòng)拋出)
? ? ? ? 注意是throw不是throws哦:
? ? ? ? 試一下運(yùn)行:
? ? ? ? 一個(gè)小技巧:但凡在編譯的時(shí)候出現(xiàn)這個(gè)錯(cuò)誤提示的時(shí)候氓涣,恭喜你,你已經(jīng)解決到了語法錯(cuò)誤的最后環(huán)節(jié)啦韭寸!在編譯的時(shí)候春哨,它先報(bào)的是最基本的語法錯(cuò)誤,如果沒有語法錯(cuò)誤恩伺,有異常的問題赴背,它會(huì)最后報(bào)告。所以晶渠,當(dāng)出現(xiàn)這個(gè)問題的時(shí)候凰荚,說明你的編譯問題已經(jīng)解決到最后了,只要把這個(gè)問題解決掉褒脯,編譯就通過啦便瑟!
? ? ? ? 繼續(xù)我們的問題。
?? ?????當(dāng)在函數(shù)內(nèi)部出現(xiàn)了throw拋出異常對象番川,那么就必須要給對應(yīng)的處理動(dòng)作到涂。
? ??????要么在內(nèi)部try catch處理,要么在函數(shù)上聲明讓調(diào)用者處理颁督。
? ? ? ? 一般情況下践啄,在函數(shù)內(nèi)出現(xiàn)異常,函數(shù)上需要聲明沉御。
????????所以我們聲明一下異常:
? ? ? ? 再運(yùn)行屿讽,繼續(xù)報(bào)錯(cuò):
? ? ? ? 繼續(xù)寫try-catch語句進(jìn)行處理:
? ? ? ? 給里面?zhèn)饕粋€(gè)負(fù)數(shù),運(yùn)行吠裆,成功啦:
? ? ? ? 我們發(fā)現(xiàn)伐谈,這個(gè)異常木有信息烂完。因?yàn)槲覀儧]有定義信息哦,剛剛那些Java已經(jīng)封裝好的異常有具體的信息诵棵,是因?yàn)樗鼈円呀?jīng)定義好信息啦抠蚣。
? ? ? ? 那么如何定義異常信息呢?
? ? ? ? 給自定義的異常添加一下內(nèi)容:
? ? ? ? 然后在Demo類中傳一個(gè)異常信息:
? ? ? ? 編譯履澳,運(yùn)行柱徙,這下就有信息了:
? ? ? ? 但是我們翻一下手冊,發(fā)現(xiàn)父類Throwable中已經(jīng)定義了這些功能啦奇昙,把它簡單還原一下大概這樣:
? ? ? ? 我們再看看它的子類Exception:
? ? ? ? 我們發(fā)現(xiàn),Exception中沒有方法敌完。但是它有一個(gè)帶有String message參數(shù)的構(gòu)造函數(shù)储耐。
? ? ? ? 再次還原一下:
? ? ? ? 既然父類已經(jīng)定義了這個(gè)方法,子類就不用重新寫啦滨溉,直接將它傳給父類處理就OK啦什湘。
? ? ? ? 所以,剛剛我們寫的那些都很多余晦攒,這樣寫就行啦:
? ? ? ? 試一試闽撤,成功啦:
?????????因?yàn)楦割愔幸呀?jīng)把異常信息的操作都完成了。所以子類只要在構(gòu)造時(shí)脯颜,將異常信息通過super語句傳遞給父類哟旗。那么就可以直接通過getMessage方法獲取自定義的異常信息。
????????接下來栋操,我們對于自己定義的問題闸餐,想有自己特有的信息,比如矾芙,想拿到到底是哪個(gè)負(fù)數(shù)值出現(xiàn)了問題舍沙。
? ? ? ? 這樣寫:
? ? ? ? 在Demo中將這個(gè)錯(cuò)誤的b傳進(jìn)去:
? ? ? ? 用catch輸出一下b的值:
? ? ? ? 運(yùn)行:
? ? ? ? 這就是我們的自定義異常。
? ? ? ??注意剔宪,在自定義異常的時(shí)候:
? ??????自定義異常類必須繼承Exception拂铡。
? ??????繼承Exception的原因:
? ? ? ? 異常體系有一個(gè)特點(diǎn):異常類和異常對象都需要被拋出。它們都具備可拋性葱绒,這個(gè)可拋性是Throwable這個(gè)體系中的獨(dú)有特點(diǎn)感帅。只有這個(gè)體系中的類和對象才可以被throws和throw操作。不是隨便定義一個(gè)類就能拋的 哈街。
????10-面向?qū)ο?throw和throws的區(qū)別)
? ? ? ? throw和throws的區(qū)別:????
? ? ? ? 1留瞳,throws使用在函數(shù)上,throw使用在函數(shù)內(nèi)骚秦。
? ? ? ? 2她倘,throws后面跟的是異常類璧微,可以跟多個(gè),用逗號隔開硬梁。throw后面跟的是異常對象前硫。
? ? ? ? 什么是函數(shù)上?
? ? ? ? 要寫在小括號和大括號之間的這里:
????11-面向?qū)ο?RuntimeException)
? ? ? ? 剛剛我們自定義了一個(gè)異常荧止,拋出的是我們自定義的內(nèi)容屹电,現(xiàn)在能不能在這個(gè)自定義的異常里面,手動(dòng)的來拋出一下算數(shù)異常呢跃巡?
? ? ? ? 算數(shù)異常中有兩個(gè)構(gòu)造方法摘要:
? ? ? ? 我們在Demo中throw一個(gè)算數(shù)異常對象:
? ? ? ? 編譯運(yùn)行:
? ? ? ? 拋一下Exception試試:
? ? ? ? 編譯失敗了:
? ? ? ? 為啥ArithmeticException就沒事呢危号?剛剛不是說函數(shù)內(nèi)拋一定要標(biāo)識(shí)嗎?
? ? ? ? 這是一個(gè)非常特殊的地方素邪。
? ? ? ? ArithmeticException往上看外莲,它有一個(gè)父類:RuntimeException,就是這個(gè)異常類兔朦,它非常的特殊偷线。如果在函數(shù)內(nèi)拋出了,函數(shù)上不用聲明沽甥。
????????還有一個(gè)就是:
? ? ? ? 按理說声邦,聲明了一個(gè)拋出異常的方法,主函數(shù)需要寫try-catch語句進(jìn)行處理摆舟,但是現(xiàn)在我們試試主函數(shù)什么都不寫編譯一下亥曹,圖略,發(fā)現(xiàn)編譯并沒有報(bào)錯(cuò)恨诱。
? ???????Exception中有一個(gè)特殊的子類異常:RuntimeException(運(yùn)行時(shí)異常)
? ??????如果在函數(shù)內(nèi)拋出該異常歇式,函數(shù)上可以不用聲明,編譯一樣通過胡野。
? ? ? ? 如果在函數(shù)上聲明了該異常材失,調(diào)用者可以不用進(jìn)行處理,編譯一樣通過硫豆。
????????為什么它這么特殊呢龙巨?
? ? ? ? 之所以不用在函數(shù)上聲明每强,是因?yàn)椴恍枰屨{(diào)用者處理厦画。當(dāng)該異常發(fā)生舞箍,希望程序停止东羹。因?yàn)樵谶\(yùn)行時(shí),出現(xiàn)了無法繼續(xù)運(yùn)算的情況炊苫,希望停止程序后医咨,由程序員對代碼進(jìn)行修改搪搏。
? ? ? ? 我們看看Runtime都有哪些子類:
? ? ? ? 它里面有很多我們常見的異常,比如空指針異常递览。
? ? ? ? 一個(gè)空指針異常的例子: ? ?
? ? ? ? name都沒有值叼屠,根本沒辦法繼續(xù)運(yùn)行,只能讓程序停下來绞铃,我們修正一下自己的代碼镜雨,才能讓它繼續(xù)運(yùn)行。
? ? ? ? 怎么修正才能避免這種情況的發(fā)生呢儿捧?
? ? ? ? 寫成這樣就好啦荚坞。
? ? ? ? 在上面的例子中,我們并沒有拋出異常菲盾,最后程序停掉了颓影,我們才能發(fā)現(xiàn)了這個(gè)問題并修正它呢。
?????????自定義異常時(shí)懒鉴,如果該異常的發(fā)生瞭空,無法再繼續(xù)進(jìn)行運(yùn)算,就讓自定義異常繼承RuntimeException疗我。
????????試一下:
? ? ? ? 因?yàn)闆]有聲明異常,所以注意主函數(shù)中也沒有處理它哦南捂,運(yùn)行:
? ? ? ? 這時(shí)候程序停下來了吴裤,程序員就會(huì)進(jìn)行對自己的代碼進(jìn)行反思:符合條件的值往進(jìn)傳,不符合條件的值就不傳啦溺健。
? ? ? ? 接著看麦牺。
? ? ? ? Object類中有一個(gè)void wai方法:
? ? ? ? 這個(gè)方法什么作用我們這里先不用管~
? ? ? ? 我們點(diǎn)進(jìn)這個(gè)方法看一下:
? ? ? ? 我們發(fā)現(xiàn),這個(gè)方法會(huì)拋出三個(gè)異常鞭缭,可是我們又發(fā)現(xiàn)剖膳,在函數(shù)聲明的時(shí)候,只拋出了一個(gè)異常:
? ? ? ? 還有兩個(gè)岭辣,它沒有聲明吱晒。因?yàn)樗鼈兌际荝untimeException的異常。(你敢做這件事情沦童,它就敢讓程序停下來仑濒,哼!)
? ? ? ? 所以拋出的異常說明它對程序的影響不大偷遗,不拋出的異常對程序運(yùn)行影響很大墩瞳,我們必須讓程序停下來好好反思一下,修正一下氏豌。
? ? ? ? 所以下回在自定義異常的時(shí)候喉酌,我們有兩種選擇:繼承RuntimeException,或者繼承Exception。
? ? ? ? 面試的時(shí)候也經(jīng)常會(huì)考這里泪电,會(huì)問它沒有拋出能不能編譯通過呀般妙?(不要傻傻說不行哦)
?????????對于異常分兩種:
? ? ? ? 1,編譯時(shí)被檢測的異常歪架。(比如Exception異常股冗,這個(gè)時(shí)候要拋出,讓調(diào)用者去處理和蚪,因?yàn)樗强商幚淼闹棺础6暶鞯漠惓#{(diào)用者也必須寫try-catch語句進(jìn)行處理攒霹,或者進(jìn)行拋出)
? ? ? ? 2怯疤,編譯時(shí)不被檢測的異常(運(yùn)行時(shí)異常。RuntimeException以及其子類)
? ? ? ? 所以在自定義異常的時(shí)候催束,我們要考慮集峦,這個(gè)問題是否可以被處理,如果可以抠刺,就繼承Exception異常塔淤,讓調(diào)用者去處理。如果不可以速妖,就繼承RuntimeException異常高蜂,讓程序停下來,我們好好修正罕容。
? ? 12-面向?qū)ο?異常練習(xí))
????????接下來备恤,通過一個(gè)示例,來講一下異常的應(yīng)用锦秒。
????????需求:
????????Teacher類:
????????Computer類:
????????走一遍:
????????接下來開始分析問題露泊。
? ? ? ? 我們講課的過程中,會(huì)出現(xiàn)各種各樣的問題旅择。比如:電腦藍(lán)屏惭笑,電腦冒煙。
????????這個(gè)時(shí)候?qū)栴}進(jìn)行描述:
????????1生真,藍(lán)屏發(fā)生后脖咐,可以進(jìn)行處理,所以需要標(biāo)識(shí)出來異常汇歹。
? ? ? ? 2屁擅,冒煙發(fā)生后,我們分兩種情況分析一下产弹。
????????先繼承Exception派歌。
????????我們定義一個(gè)值state弯囊,如果它為1,表示正常胶果。如果它為其它值匾嘱,表示出問題了。
? ? ? ? 如果藍(lán)屏早抠,我們就讓它重啟:
????????重啟就讓它的狀態(tài)恢復(fù)到1了霎烙,這時(shí)候給重啟函數(shù)中加一句:
????????如果冒煙了,會(huì)出現(xiàn)講課進(jìn)度無法繼續(xù)蕊连,這個(gè)時(shí)候悬垃,出現(xiàn)了講師的問題:課時(shí)計(jì)劃無法完成。這時(shí)候需要定義一下講師的異常:
????????所以冒煙時(shí)甘苍,拋出講師的異常:
????????注意test的調(diào)用要放在throw前面哦尝蠕,放在后面就不會(huì)被執(zhí)行到。(return語句也是這樣载庭,放到它后面就不會(huì)被執(zhí)行到了)
????????主函數(shù)中:
????????編譯運(yùn)行:
????????到這里問題基本解決啦看彼,但還有一個(gè)可以完善的地方。換老師或者放假總得有個(gè)理由吧囚聚,我們改成這樣:
????????主函數(shù)中加一句這個(gè):
????????編譯運(yùn)行:
? ? ? ? 心好累靖榕。