????01-面向對象(內部類訪問規則)
? ? ? ? 內部類:
????????從名稱上直觀的來分析, 這個類是已經定義到另外的類的里邊啦。
? ? ? ? 所以,將一個類定義在另一個類的里面,對立面那個類就稱為內部類(又叫內置類,嵌套類)。
? ? ? ? 比如:
? ? ? ? 訪問特點:
? ? ? ? 內部類可以直接訪問外部類中的成員,包括私有成員。
? ? ? ? 而外部類要訪問內部類中的成員必須要建立內部類的對象。
????????這就相當于孫悟空要找到牛魔王的心臟,就要先找到牛魔王再找到它的心臟,就是牛魔王.get心臟()方法。但是孫悟空如果跑到牛魔王肚子里面去了,他訪問牛魔王的心臟就可以直接訪問啦。
? ? ? ? 我們可以直接訪問內部類中的成員嗎?
? ? ? ? 可是如果還有一個類叫Outer2,里面也有個內部類叫Inner,怎么區分是哪個類里的內部類呢?
? ? ? ? 所以一定要指明是哪個類里的Inner()。
? ? ? ? 右邊格式也要改一改呢,要寫成醬紫:
? ? ? ? 但是這個很少被用到,因為內部類可能會被私有,就無法直接訪問了。這個只是一種格式,應該只有面試的時候可能會用到。
????????類可以被私有嗎?
? ? ? ? 內部類可以被私有。當一個類是另一個類的內部類時,可以被私有。
? ? ? ? 但是一般的類絕對不可以私有。
? ? ? ? 為什么內部類可以直接訪問到外部類的內容??
? ? ? ? 一個例子。
? ? ? ? 如果想打印x=6,則:
? ? ? ? 如果想打印x=4,則:
? ? ? ? 如果想打印x=3,則:
? ? ? ? 當然,如果內部類里面沒有另外定義x=4和x=6,那么打印x就默認打印的是外部類的x=3。這個時候x前面有隱式的Outer.this。
? ? ? ? 之所以內部類可以直接訪問外部類中的成員,是因為內部類中持有了一個外部類的引用,格式 外部類名.this。
? ??02-面向對象(靜態內部類)
? ? ? ? 訪問格式:
? ? ? ? 1,當內部類定義在外部類的成員位置上,而且非私有,可以在外部其他類中,直接建立內部類對象。
? ? ? ? 格式:
? ? ? ? 外部類名.內部類名 變量名=外部類對象.內部類對象;
? ? ? ? 即 Outer.Inner in=new Outer().new Inner();
? ? ? ? 2,當內部類在外部類的成員位置上,就可以被成員修飾符所修飾。
? ? ? ? 比如,private:將內部類在外部類中進行封裝。
? ? ? ? ? ? ? ? ? static:內部類就具備static的特性。當內部類被靜態修飾后,只能直接訪問外部類中
? ? ? ? ? ? ? ? ? 的static成員,出現了訪問局限。
? ? ? ? ? ? ? ? 在外部其他類中,如何直接訪問static內部類的非靜態成員呢?
? ? ? ? ? ? ? ? 這樣即可:
? ? ? ? ? ? ? ? 如果fuction()也靜態了呢?
? ? ? ? ? ? ? ? 這樣即可:?
? ? ? ? ? ? ? ? 但是使用頻率很低。
? ? ? ? 注意:當內部類中定義了靜態成員,該內部類必須是靜態的。否則會報錯。
? ? ? ? 這樣才對:
? ? ? ? 再一個例子:
? ? ? ? 改成醬紫就OK啦:
????????注意:當外部類中的靜態方法訪問內部類時,內部類也必須是靜態的。
? ??03-面向對象(內部類定義原則)
? ? ? ? 當描述事物時,事物的內部還有事物,該事物用內部類來描述。
? ? ? ? 因為內部事務在使用外部事物的內容。
? ? ? ? 比如心臟之于人體。
? ? ? ? 我們的心臟不可以直接被其他人訪問到,所以要私有。
? ? ? ? 當一個類需要直接訪問到另外一個類中的成員的時候,就把另外一個類寫到這個類的里面。寫完之后,爭取把這個類封裝在外部類中,不被外暴露,而是對外提供一個方法進行訪問。
????04-面向對象(匿名內部類)
? ? ? ? 我們發現,剛才寫的內部類,定義在外部類的成員位置上,只有定義在成員位置上的內部類,才可以被私有或靜態修飾。一般內部類是不會被公有修飾的。有沒有這種情況呢?有。比較特殊的情況會出現。這個就不說啦。
? ? ? ? 除了定義在外部類的成員位置上,內部類還可以寫在其他位置上呢,比如寫在外部類的方法當中:
? ? ? ? 這個類就是局部的。但是訪問規則沒有變,它還是可以直接訪問外部類中的成員。
? ? ? ? 那它還能被靜態所修飾嗎?不能。因為靜態修飾符只修飾成員,現在它是局部的,所以不能被修飾了。那它還能定義靜態的成員嗎?不能。因為內部類中若有靜態成員,這個內部類也必須是靜態的,所以它也不可以定義靜態的成員。
? ? ? ? 現在調用這個內部類中的function,因為必須要有這個內部類的對象才可以頂用它,所以要這樣寫:
? ? ? ? 可以看到運行是沒有問題的。
? ? ? ? 這是內部類定義在局部位置上的一個小特點。
? ? ? ? 為什么不把定義內部類對象放在前面呢?會報錯的:
? ? ? ? 因為如果放在前面,類定義又在后面,定義內部類對象的時候,還沒有讀到這個類的定義呢。所以內部類對象的定義要放在內部類的定義的后面。
? ? ? ? 那么內部類是否可以訪問它所在的方法中定義的變量y呢?會報錯:
? ? ? ? 這樣就OK啦:
? ? ? ? 內部類定義在局部時:
? ? ? ? 1,不可以被成員修飾符修飾。
? ? ? ? 2,可以直接訪問外部類中的成員,因為還持有外部類中的引用。
? ? ? ? ? ? ? 但是不可以訪問它所在的局部中的變量,只能訪問被final修飾的局部變量。
? ? ? ? 這個a可以被打印嗎?
? ? ? ? 不可以喔。
? ? ? ? 為什么呢?
? ? ? ? 因為a是一個變量,需要被final修飾才能訪問。
? ? ? ? 像醬紫:
? ? ? ? 這時候就郁悶了,a不就變成常量了嘛?那底下不是又給a賦值7,這不是很矛盾嗎?
????????這其實沒問題,把7賦值給a,這之后a就被鎖住了。看,運行沒有問題的:
? ? ? ? 試試再給它賦值為8:
? ? ? ? 或者這個形式:
? ? ? ? 不過,對于給a賦值來說,這兩種方法一點區別都沒有。
? ? ? ? 因為a并不是在對象中。它是標準的局部變量。這兩種方法如果是給x賦值,就會有區別的。
? ? ? ? 好,其實不管哪種方法,這樣都是可以編譯通過的,為什么呢?a不是常量嗎?
? ? ? ? 分析一波:調用method()方法,它就進棧內存了, 棧里也有a,把7賦值給a,鎖住了,a就一直為7。直到out.method(7)這句話執行完了,就要出棧了,釋放了。下一句話,再調用method(),又進棧了,就是新的a了,這時把8賦值給a,a鎖住了。所以這樣是OK的。
? ? ? ? 那什么情況是不OK的呢?
? ? ? ? 醬紫就不闊以哦:
? ? ? ? 匿名內部類:
? ? ? ? 1,匿名內部類其實就是內部類的簡寫格式。
? ? ? ? 2,定義匿名內部類的前提:內部類必須是繼承一個類或者實現接口。
? ? ? ? 比如每個人都是有心臟的,在外部定義一個抽象的心臟,所有人的內部的心臟類都繼承它,繼承它里面的方法。
? ? ? ? 這是一個常規的內部類:
? ? ? ? 我們現在要把它簡化成一個匿名內部類。怎么簡化呢?
? ? ? ? 綠色的部分,其實就是我們需要簡化的部分。
? ? ? ? 簡化之前我們先分析一下,內部類都做了什么事情呢?
? ? ? ? 1,它繼承了一個類;2,復寫父類的方法;3,創建對象;4,調用。
? ? ? ? 這個內部類本來的名字叫Inner,現在沒這個名字了,我們怎么調用它呢?
? ? ? ? 醬紫來:
? ? ? ? 因為是寫匿名,所以這個時候Inner沒有了,我們把它改成父類的名字:
? ? ? ? 這個時候需要覆蓋父類的方法,繼續:
? ? ? ? 這樣就OK啦。這就是一個匿名內部類,也是一個帶著內容的對象,一個很胖噠對象!
? ? ? ? 記住:這個整體是一個對象!是一個什么對象呢?是AbsDemo的子類對象,因為只有子類才能復寫AbsDemo中的抽象方法。這個整體就是綠色部分的簡化寫法~
? ? ? ? 這種寫法很簡化,但是可能不是很好理解。但是開發中這種寫法非常常見。
? ? ? ? 所以接著上面,匿名內部類:
? ? ? ? 3,匿名內部類的格式: ? ?new 父類或者接口(){定義子類的內容}
? ? ? ? 4,其實匿名內部類就是一個匿名子類對象。而且這個對象有點胖。可以理解為帶內容的對象。
? ? ? ? 也可以在里面寫其它函數并調用哦:
? ? ? ? 如果又想調用abc(),又想調用show()呢?醬紫:?
? ? ? ? 但是這樣太麻煩了,能不能起個名字呢?但是不是匿名類嗎?不是不可以起名字嗎?但是可以這樣:
? ? ? ? 這其實就是多態中的父類調用子類對象。但是第二個abc就不可以被父類調用,因為abc是子類的方法,父類中沒有定義。所以這樣只能調用父類方法,不能調用子類方法,感覺意義也不大。我們寫匿名類就是為了簡化書寫,這樣一來感覺更麻煩了。
? ? ? ? 匿名內部類是有局限性的。它的出現就是為了簡化書寫,所以這樣一來有好處也有弊端,弊端就是直接調用自己的方法還不行(就是上面那種情況),還有一個弊端,就是父類里面的方法過多的話就不要定義匿名內部類了,比如:
? ? ? ? 匿名內部類里面就是這樣的:
? ? ? ? 這樣如果你想調用的話,就會非常麻煩,里面那么多方法,閱讀性已經沒有了,如果每個方法里面的代碼再多一點,這就是一屏(甚至好幾屏)的代碼,我們都沒眼看了!
? ? ? ? 所以,一般寫匿名內部類,它里面的方法不會超過三個,大多兩個或一個,這樣匿名對象調用方法就會方便很多。
? ? ? ? 所以,再接前面的,匿名內部類:
? ? ? ? 5,匿名內部類中定義的方法最好不要超過3個。
? ? ? ? 那如果沒辦法,父類里的方法就是那么多怎么辦?那就按常規的內部類來咯,定義一個內部類,繼承它,后面可以建立這個類的內部對象慢慢一個個調用~
? ? ? ? 匿名內部類就是在方法少的情況下,可以簡化書寫、方便調用,里面寫得太復雜就失去意義了。
? ? ? ? 下面來一個小練習:
? ? ? ? 分析一下這句話:
? ? ? ? Test類中肯定有靜態成員,而且這個靜態成員方法的名字叫function。
? ? ? ? 所以,可以確定先寫成這樣:
? ? ? ? 繼續分析這句話:
? ? ? ? 調用完function之后緊接著又調用了method方法,從前面Inter接口的內容可以看出,method是非靜態的(因為它是抽象的所以一定是非靜態的)。由此可以推出,Test調用了function的運算結果是一個對象。因為只有返回了對象,對象才能調用method方法。
? ? ? ? 我們想想哪個對象可以調用method?必然是Inter的對象。所以返回值類型也確定了,是Inter:
? ? ? ? 我們先用內部類來寫一遍,運行是沒有問題的:
? ? ? ? 接下來用匿名內部類來寫:
? ? ? ? 總結回顧一下:
? ? ? ? 有一種需要用匿名內部類的情況很常見,說一下:
? ? ? ? 現在的想法是,調用show(),這個括號里面是不是要傳進來一個接口類型的對象。
? ? ? ? 我們可以怎么做呢?
? ? ? ? 分解做的話就是,先搞一個類,去把這個接口實現一下,這個類定義在內部也行,定義在外部也行,定義完之后,把這個類的對象作為參數傳給show方法。但是這么做很麻煩。
? ? ? ? 當使用的對象是接口類型時,查看一下這個接口里的方法,如果不超過三個,我們可以定義一個匿名內部類,把匿名內部類作為參數傳進去。
? ? ? ? 醬紫:
? ? ? ? 萬一沒有父類,也沒有接口,就是想調用一個function方法,還可以寫匿名內部類嗎?
? ? ? ? 厲害的來啦,我們可以new一個Object對象。
? ? ? ? 對了,一定要注意:
? ? ? ? 后面帶分號:
? ? ? ? 后面是大括號:
? ? ? ? 好,這樣就OK啦:
? ? ? ? 然后我們還想加一個函數,這個時候就需要給它起名字:
? ? ? ? 注意這樣是不可以的哦,這時一個錯誤示例,以為Object類里面并沒有定義這個方法,所以不可以這樣調用。
????05-面向對象(異常概述)
? ? ? ? 什么叫異常呢?就是我們所謂的不正常。
? ? ? ? 寫了一個除法的小程序:
? ? ? ? 但有時候會傳不合法的值進去,我們會發現,編譯的時候沒有問題,但是運行的時候出現了問題,程序不正常結束了:
? ? ? ? 這就是我們所說的異常。
? ? ? ? 異常:就是程序在運行時出現的不正常情況。
? ? ? ? 異常由來:問題也是現實生活中一個具體的事物,也可以通過java的類的形式進行描述,并封裝成對象。
? ? ? ? 其實就是java對不正常情況進行描述后的對象體現。
? ? ? ? 對于問題的劃分,它分成兩種:一種是嚴重的問題,一種是非嚴重的問題。
? ? ? ? 對于嚴重的,java通過Error類進行描述。
? ? ? ? ? ? ? ? 對于Error,一般不編寫針對性的代碼對其進行處理。(就好像得了癌癥一樣,只是進行保守治療,沒有什么針對性的治療方式可以藥到病除了)
? ? ? ? 對于非嚴重的,java通過Exception類進行描述。
? ? ? ? ? ? ? ? 對于Exception可以使用針對性的處理方式進行處理。(對于感冒發燒,可以喝感冒藥治好)
? ? ? ? 所以我們重點講能處理的部分,也就是Exception。
? ? ? ? 一個內存溢出的例子:
? ? ? ? 虛擬機本身有自己啟動的默認空間,任何一個軟件啟動都會劃分到這個默認空間來存放數據,但是虛擬機它的空間是有限的,就這么大,你非要開一個超過它的大小,就掛掉了。道理很簡單,超出虛擬機的范圍。
? ? ? ? 虛擬機在啟動的時候,可以通過它提供的參數,來將它改變成更大的空間。但是你分配多大都沒用,如果數組這個空間,已經超出物理內存空間的話,再改變也沒戲。就像這個問題,怎么處理也沒戲。
? ? ? ? 那Error和Exception有沒有共性呢?
? ? ? ? 有的。
? ? ? ? 拿感冒發燒來舉例,這兩個疾病都有它的名稱,都有發病原因。
? ? ? ? 無論Error或者Exception都具有一些共性內容。
? ? ? ? 比如:不正常情況的信息,引發原因等。
? ? ? ? 那么它們有了共性會向上抽取,抽取完了之后就會形成一個基本的體系,抽取出來的這個父類就叫做Throwable,Throwable下面就兩個子類,一個叫Error,一個叫Exception,而這兩個類的下面會有很多的子類出現。(就像感冒發燒一樣,也會劃分為不同類型的感冒)
? ? ? ? 我們來看一下Java的API文檔,看看它是怎么對這個體系進行介紹的。
? ? ? ? 在java.lang中,有一個Throwable類。Throw是拋的意思,加上able就是可拋的意思。
? ? ? ? Throwable是Java中所有異常的父類(超類)。
? ? ? ? 在這個類中,就定義了這個體系的共性內容。那么要使用一個體系,是不是就要看這個體系的父類父類的定義,建立子類的對象。
? ? ? ? 來看一下這個類的定義。它繼承了Object,實現了Serializable。它有兩個直接子類,而我們要講的就是Exception。
? ? ? ? 先看Error:
? ? ? ? Error的小弟好多哦!而且我們發現,它的小弟名字最后都有Error。所以,Java在命名的時候,會把父類名稱放在子類名字的最后,這個也是我們以后開發中可以借鑒的呢!而且這樣命名,誰是它的父類,它是誰的子類也一目了然辣!
? ? ? ? 我們再看下Exception:
? ? ? ? 哇!它的小弟更多了耶。我們要把它們都學完嗎?
? ? ? ? 試著點進其中一個子類,發現:
? ? ? ? 小弟竟然還有小弟,嗚嗚,學不完這么多呀。
? ? ? ? 所以說我們把根本性的東西搞定就行了。
? ? ? ? Java把一些常見的問題都進行描述,并封裝成異常了。
? ? ? ? 這就是異常的基本的體系。
????06-面向對象(異常try-catch)
? ? ? ? 接下來我們的程序已經發生異常啦!我們是不是可以用拋出異常來處理呢?
? ? ? ? 就因為被除數為0,所以拋出了異常,我們需要處理一下。為什么呢?因為就因為這個小問題,導致后面的都不能運行了,哼!怎么辦呢?
? ? ? ? 在解決之前我們先了解一下這個拋出異常的過程。
? ? ? ? Java虛擬機,它認識這個叫ArithmeticException的異常,因為這是它定義的。引發了它所熟悉的狀況,它就給你處理了。那是因為,Java虛擬機內部,有一個內置的異常處理機制。它把它熟悉的異常就給搞定了,但是搞定的方式很簡單,就是只要程序出現問題,就不再往下運行。但是我們希望的是,把問題處理掉。
? ? ? ? 這時候就涉及到第二部分,異常的處理。
? ? ? ? 對于異常的處理,java為我們提供了特有的語句進行處理。
? ? ? ? try
? ? ? ? {
? ? ? ? ? ? ? ? 需要被檢測的代碼;
? ? ? ? }
? ? ? ? catch(異常類 變量)
? ? ? ? {
? ? ? ? ? ? ? ? 處理異常的代碼;(處理方式)
? ? ? ? }
? ? ? ? finally
? ? ? ? {
? ? ? ? ? ? ? ? 一定會執行的語句;
? ? ? ? }
? ? ? ? 現在我們改寫一下剛剛的代碼,over就被打印啦。
? ? ? ? 我們來說一下這個異常:
? ? ? ? 有一個小問題,catch中,處理這個問題并沒有用到傳進來的對象e。
? ? ? ? 想用呀?沒問題~
? ? ? ? catch接收到異常后,相當于這個~
? ? ? ? 這是不是多態呀?父類的引用指向子類的對象。
? ? ? ? 想操作這個e該怎么辦呢?當然是找方法。而異常對象的共性方法定義在Throwable當中。我們去Throwable當中看一下,都有什么方法呢?
? ? ? ? 心好痛啊
? ? ? ? 不管怎樣,我都會好好努力的。
? ? ? ? 我們發現,這里有個getMessage方法,可以獲取信息,它返回的是一個字符串。
? ? ? ? 對捕獲到的異常對象進行常見方法操作:
? ? ? ? String getMessage();//獲取異常的信息
? ? ? ? 試一下:
? ? ? ? 還有一個方法也可以:
? ? ? ? 試一下:
? ? ? ? 這個打印的就更全面啦,既有異常的信息,又有異常的名字。
? ? ? ? String toString();//打印:異常名稱:異常信息
? ? ? ? 還有這個方法:
? ? ? ? 打印堆棧中的跟蹤信息。注意,這個方法沒有返回值,所以不要放到輸出語句當中輸出,它本身自己就可以打印了。
? ? ? ? 試試:
? ? ? ? 它是不是hin全面呀?既有異常名稱、異常信息,同時又有異常的位置。
? ? ? ? void printStackTrace();//打印:異常名稱,異常信息,異常出現的位置。
? ? ? ? 其實jvm默認的異常處理機制,就是在調用printStackTrace方法,打印異常的堆棧的跟蹤信息。
????07-面向對象(異常聲明throws)
????????接下來問題來了,這個功能是別人編寫的,你在使用的時候,一定要做try處理嗎?不一定。為什么呢?因為你根本不知道這個功能會不會發生問題。所以,這個問題你可處理可不處理,這樣會導致一個現象,你在傳參數的時候這個程序可能會停掉。
? ? ? ? 所以這樣開發是不OK的,怎么做是OK的呢?
? ? ? ? 作為編寫Demo的人,在編寫了除法方法的時候,就要考慮到有可能會出現傳進來的被除數為0的情況,這個時候就要在方法上做一個標識,告訴調用這個方法的人,“這個方法可能會出現問題哦”。這個標識就是throws。
? ? ? ? 標識完會出現什么現象呢?
? ? ? ? 我們試一下:
? ? ? ? 對方聲明了一個功能:這有可能發生問題。而這個問題,它又解決不了,它就把問題告訴給調用者。
? ? ? ? 而這個時候,作為調用者,對方已經告訴你有可能發生問題,這個時候你需要做的就是:處理。
? ? ? ? 如果你不處理,就會編譯失敗,不處理它就不讓你用哦。它也是為了提高安全性。
? ? ? ? 那該怎么處理呢?
? ? ? ? 我們再來讀一下這個報錯:
? ? ? ? 我們處理問題的方式有兩種,要么捕捉它,要么拋出去。
? ? ? ? 處理方式1:
? ? ? ? 我也不管!把它拋出去!
? ? ? ? 這是拋給誰了呢?拋給了虛擬機。結果是這樣的:
????????所以問題還是沒有解決。
????????一般情況下,我們不拋,而是捕捉一下。(后面還會講什么時候拋,什么時候try,這是有區別的。)
? ? ? ? 醬紫來寫,運行一下,OK的喔:
? ? ? ? 來一個傳了錯值的:
? ? ? ? 用一個例子比較一下拋出和捕捉這兩種方式的不同:
? ? ? ? 有一個面包店,它家有一塊面包放了三天都沒有賣出去,這個時候這塊面包就有可能會壞掉了。所以良心的店主給上面貼了個標簽:放置三天后可能會壞。然后將它降價處理,從3塊錢降到3毛錢。有個人就把它買走啦。
? ? ? ? 拋出:回家之后一想,這個有可能壞掉,我也不知道該怎么解決,就把它給別人吧,有可能這個人也會給別人,但總會有個終點,就相當于虛擬機。都別吃啦!
? ? ? ? 捕捉:把它放在微波爐里加熱一下(catch),然后吃掉(最后正常執行的println(“over”);)。
? ? ? ? 有點不太恰當~
????08-面向對象(多異常處理)
? ? ? ? 我們在定義功能的時候,有可能會發生不止一個問題,我們在函數上聲明異常的時候,聲明的也就不只一個了。像剛剛聲明的異常throws Exception,這個方式其實不是很好。因為它太廣義啦,這里的問題是除法運算中可能會出現被除數為0的情況,如果聲明得再具體一些,我們就能處理得更具體了。
? ? ? ? 這個才是我們一般處理的方法。
? ? ? ? 聲明異常時,建議聲明更為具體的異常,這樣處理的可以更具體。
? ? ? ? 比如在剛剛那個例子中,我們就可以拋出算數異常:
? ? ? ? 再多寫一些語句,來看一下多種異常的情況:
? ? ? ? 調用時的處理:
? ? ? ? 注意聲明了幾個異常,調用的時候就要寫幾個catch語句哦。
? ? ? ? 沒有出現異常的情況:
? ? ? ? 出現算數異常的情況:
? ? ? ? 出現數組角標異常的情況:
? ? ? ? 那會不會兩種異常同時發生呢?不會。因為當出現一個異常之后,這個異常就被拋出了,后面的語句就不會執行了哦。
? ? ? ? 我們不寫這么多catch,也一個catch可以嗎??
? ? ? ? 這樣來寫:
? ? ? ? 它存在的原因是多態性。不管拋什么異常它都可以處理。但是它處理沒有針對性哦。
? ? ? ? 所以最好寫上有針對性的處理,每種異常要有與之匹配的catch。所以一般聲明了幾個拋出異常,調用時就應該寫幾個catch。
? ? ? ? 這時候又有個問題,調用者擔心萬一發生的問題是那兩個之外的,又寫了一個catch語句:
? ? ? ? 這樣寫也不是不可以,但是它有一個問題,就是處理的不具體。也就是說,你都不知道具體發生了,就把這個問題干掉了,相當于把這個問題隱藏了。而程序還在繼續運行,也就是說,程序不知道發生什么事情了,繼續在運行當中。為了安全性考慮,如果這個時候發生了對方指定的問題以外的問題,這個時候最好的處理方式就是:程序停掉。因為我們得知道,到底哪里卡住了,哪里出問題了,哪里是需要修正的。不能莫名其妙的把問題處理掉,發生了什么都不清楚。
? ? ? ? 所以這個時候依舊寫兩個catch,當發生第三種問題的時候,我們就是要讓程序停下來,來尋找這第三個問題到底是什么,把它標識出來,聲明出來,調用的時候也可以提出具體的更有針對性的解決方法。
? ? ? ? 注意,還有一種情況:
? ? ? ? 運行之后會這樣:
? ? ? ? 第一個catch是大哥,后面兩個是小弟,發生什么問題,大哥都能處理。因為catch是按順序執行,而第一個catch都能處理,所以后面兩個catch的存在,跟廢話一樣,永遠執行不到。所以就報錯了。
? ? ? ? 綜上:
? ? ? ? 對方聲明幾個異常,就對應有幾個catch塊。不要定義多余的catch塊。
? ? ? ? 如果多個catch塊中的異常出現繼承關系,父類異常catch塊放在最下面。
? ? ? ? 建議在進行catch處理時,catch中一定要定義具體的處理方式。
? ? ? ? 不要簡單定義一句e.printStackTrace(),也不要簡單的就書寫一條輸出語句。(剛剛那樣寫只是在演示,正式編寫中不是這樣簡單處理的哦)因為打印它沒有意義,用戶看到了又能怎樣呢?真正發生問題之后,一般會用一個文檔把這些異常信息記錄下來,記錄完之后,我們把它稱為異常日志文件。這樣,在我們運行過程中,每天都會產生這些文件,記錄了我們程序每天的運行狀況:在什么時候幾點幾分,發生了一個什么問題。管理人員/網站的維護人員,就會經常去看這個日志,看完之后就會知道什么時候在代碼的什么位置發生了什么問題,然后去把它搞定一下,看看為什么會產生這個問題,這個問題是不是大問題。所以,用文件記錄下來,這是靠譜的。