《Java程式設計》第七次學習總結
《Java程式設計》第七次學習總結
目錄
教材學習內容總結
教材學習中的問題和解決過程
程式碼除錯中的問題和解決過程
其他(感悟、思考等,可選)
正文
教材學習內容總結
學習了第十一章“異常”和第十二章“遞迴”。自己思考後總結如下:
- 第十一章
- 異常就是那些有可能出現錯誤的情況,而不是一定就是錯誤。
- 異常分為兩類:“必檢異常”和“非必檢異常”,在有可能會丟擲“必檢異常”的方法名後面得加上
throws()
關鍵字,方法體中用throw
來丟擲可能發生的異常。 try()catch(){}
語句塊中可以有多個catch(){}
欄位,分別來對應處理可能會出現的錯誤。- 如果有
try()catch(){}
欄位,則代表:對相應的異常進行了捕獲並處理 ,那麼異常發生後面的程式也可以被執行。反之,如果沒有try...catch
欄位則一遇到異常就會終止這段程式的執行,如果是被呼叫的則轉向呼叫的方法那裡,如果是main方法就直接結束整個程式了,並且打印出棧呼叫的軌跡和相應的異常資訊。 - 不論是正常退出try塊,還是因丟擲一個異常而退出try塊,都要執行finally字句。
- 第十二章 : recursion
- 遞迴的思想:自己呼叫自己來解決問題。有個例子是:用decorate 來解釋decarate的意思。包括自己在學c語言時候就知道的用遞迴的方法來解決階乘的問題。
- 關於遞迴,新的收穫有:其實一個遞迴有兩部分組成:
- 基礎情形:base case;
- 呼叫自身的過程。
- 這裡的基礎情形可以讓呼叫自身這個過程不會無休止的進行下去(即:不會產生無窮遞迴),當自身呼叫自身過程到了base condition時,就會執行base condition 並且沿著一開始呼叫自身的“路徑”,開始往回“走”,一層一層的返回得到的值,只到回到最初的那個呼叫自身的開始處。
- 由上面那個遞迴由兩部分構成這個結論,可以想到:實現遞迴最基本的結構就是
if-else
語句,用if-else
其中某個分支來處理基礎情形(base case)的情況,另外一個分支負責來呼叫自身。 - 每次呼叫自身,都會導致方法中的區域性變數重新被更新,而且,在往回走的時候區域性變數會自動回到上一次呼叫它時候的值,概念就是:形參在函式內的變化不會傳遞到呼叫這個函式的實參上。
- 直接遞迴和間接遞迴。
- 關於遞迴的書上的例子說明:
教材學習中的問題和解決過程
- 問題一:關於
throws
關鍵字和throw
的區別,還有try-catch
語句塊。問題的詳細描述如下:什麼時候需要用到throws
?用在哪裡?throw
關鍵字也是有同樣的問題?很明顯的一個就是,好像在使用java自帶的又可能出現異常的方法的時候就不需要用到throws
和throw
關鍵字了,如果要捕獲異常得用到try-catch
語句塊。但是,如果你自己程式設計序來自定義一個自己想要的必檢異常,那麼則需要用到throws
關鍵字來附加到函式名字的尾部,同時,在會發生異常的部分來使用throw
關鍵字來丟擲異常。同理捕獲得用那個語句塊。 - 解決方法:上面自己的想法,大部分是對的。理一下:異常分為系統給出的異常,以及你自定義的異常。
- 系統給出的異常中有必檢和非必檢兩大類,在呼叫這個有可能會出現異常的方法時,必須得在try語句塊中呼叫,否則會報錯“未報告異常錯誤”。
- 自定義異常時就是得同時用到
throws
和throw
,這兩個關鍵字。
throws
是用在方法名的後面throws xxxxException
,這個方法就是那個可能會出現異常的方法。而throw
關鍵字是用在這個方法體之中,通常是在一個if-else
的某一個分支中,這個分支對應了出現了異常時應該進行的操作,即:使用throw
關鍵字來丟擲異常類物件。異常類是你自己自定義的異常類xxxxException
。定義這個異常類時注意是用到extend
關鍵字來繼承Exception
類的。
程式碼除錯中的問題和解決過程
- 問題一:在程式設計時出現了,以前遇到過的“無限迴圈”的情形,明明輸入了停止字串,但是依然不能夠終止程式的執行。程式碼如下:
- 解決方法:就如自己所感受到的,明明輸入了"DONE"但是程式並不會停止執行,其實應該很自然的想到是控制迴圈的條件出了問題,但是我是通過在IDEA中進行Debug來發現是控制迴圈的條件
"DONE" != str_input
有問題的,我發現我輸入的"DONE"字串str_input
根本和不等號的右邊 "DONE" 是不等的。然後就知道了,什麼是物件的別名,什麼是物件的引用,我上圖程式中的做法是在比較str_input
這個 “門牌號” 會不會等於DONE,這當然永遠不等啊!而我的初衷是想比較str_input
這個“門牌號”對應的房間裡住著的內容是不是DONE
,不是來比較“門牌號”的。 所以正確的做法如下圖:
。
這裡充分體現了“門牌號”的概念,而且我自己編了一個程式,所以對書上之前講的一點內容有了更深入的理解:自己編的程式如下圖所示:
實際上,字串常量str3
就是一個給門牌號賦值的過程,它使得str3這個門牌號就是Hello,而不是像str1或者str2那樣的數字門牌號,所以那一條語句才是真的。
書上的內容如下:
由此可見:在比較物件時,“ == ” 是用來判斷這個關係操作符左右兩邊的“門牌號”是否是貼在一個房間的門上,如果這兩個門牌號對應是兩個單獨的房間則是不等的,只有兩個門牌號貼在同一個房間上才是等的。
所以,比較字串物件內容是否是相等的,只能呼叫方法equals()
,不能用關係操作符 “==”, 這是和麵向過程程式設計不同的!
- 問題二:遞迴呼叫時:成員變數和區域性變數的差別。
- 解決方法:這個問題出現的主要願意是在編pp12.9時出現的,原來的程式如下圖:
length 是一個區域性變數,每次遞迴呼叫時都會重新初始化,並且返回時,也能夠正常返回到原來的初始值。但是 n 就不一樣了,n是一份成員變數,我每次遞迴呼叫getValue()
方法時,n的確初始值是對的,因為有 n = number
,每次遞迴呼叫時的 number
是在變化的,但是遞迴返回時,就有問題了,遞迴返回時,因為n 是成員變數,所以你在 getValue()
方法中對 n 進行的操作都會被儲存著,它並不像形參 number 那樣對實參沒有影響,n並不能回到呼叫它時侯的方法。
這一點通過Debug也能看出來,所以,在用遞迴程式設計時候,儘量去用區域性變數,而不是去用成員變數。
- 問題三:是在做pp11.1時候出現的,關於Scanner類中的方法
next()
。 - 解決方法:要知道,每使用一次scan.next()方法一次,就是相當於呼叫了一次這個方法了,這樣的話就是相當於要使用者輸入了兩次。但是我的初衷只是,在第二次用scan.next() 時把第一次呼叫該方法的值得到。所以,正確的做法是,把第一次呼叫next()方法,得到的值儲存在一個門牌號對應的房間裡。然後,後面在用這個房間裡的東西來進行比較。下面是一開始的錯誤程式碼:
改正以後就出現了上面第一張圖裡的str_input
變數名。
其他(感悟、思考等,可選)
這一次的學習讓我對遞迴有了更深的瞭解,同時也反映了我以前基礎不紮實的事實。但是,自己能夠編寫程式來驗證自己的猜想,是一個很不錯的做法。就是想自己來猜想 ==這個運算子的時候,一開始還沒有反應過來這是門牌號的差異。所以就想著自己編個簡單的程式來驗證一下 == 真的不能用來比較相等嗎?一程式設計序,發現真的不對,然後就去反思了。所以,以後出現了問題,真的可以嘗試編一個簡單的小程式來驗證自己的想法。
學習進度條
程式碼行數(新增/累積) | 部落格量(新增/累積) | 學習時間(新增/累積) | 重要成長 | |
---|---|---|---|---|
目標 | 5000行 | 30篇 | 400小時 | |
第七次 | 2329/5000 | 1/18 | 無記錄 | 遞迴和驗證的方法思想 |
[回到目錄](#index)
參考資料
- [Java程式設計(第8版)]
- [《Java程式設計基礎(第2版)》耿祥義]