2022-06-10 分類: 網(wǎng)站建設(shè)
有些代碼必須捕獲異常,捕獲異常需要進(jìn)行周密的計劃。
如果某個異常發(fā)生的時候沒有在任何地方進(jìn)行捕獲,那程序就會終止執(zhí)行,并在控制臺上打印出異常信息,其中包括異常的類型和堆棧的內(nèi)容。對于圖形界面程序(applet和application應(yīng)用程序),在捕獲異常之后,也會打印出堆棧的信息,但程序?qū)⒎祷氐接脩艚缑娴奶幚硌h(huán)中(在調(diào)試基于圖形界面的程序時,最好保證控制臺窗口可見,并且沒有被極小化)。
捕獲一個異常,必須設(shè)置try/catch語句塊,如果在try語句塊中的任何代碼拋出了一個在catch+句中說明的異常類,那么:
1.程序?qū)⑻^try語句塊的其余代碼。
2.程序?qū)?zhí)行catch子句中的處理器代碼。
如果在try語句塊中的代碼沒有拋出任何異常,那么程序?qū)⑻^catch子句。
如果方法中的任何代碼拋出了一個在catch+句中沒有聲明的異常類型,那么這個方法就會立刻退出(期待調(diào)用者為這種類型的異常設(shè)計了catch子句)。
需要注意,try語句中的大多數(shù)代碼都很容易理解:讀取并處理文本行,直到遇到文件結(jié)束符為止。正如在JavaAPI中看到的那樣,read方法有可能拋出一個IOException異常。在這種情況下,將跳出整個while循環(huán),進(jìn)入catch子句,并輸出堆棧情況。對于一個普通的程序來說,這樣處理異?;旧虾虾跚槔?。還有其他的選擇嗎?
通常,最好的選擇是什么也不做,而是將異常傳遞給調(diào)用者。如果read方法出現(xiàn)了錯誤,就讓read方法的調(diào)用者去操心!如果采用這種處理方式,就必須聲明這個方法可能會拋出一個IOException。
請記住,編譯器嚴(yán)格地執(zhí)行throws說明符。如果調(diào)用了一個拋出已檢查異常的方法,就必須對它進(jìn)行處理,或者將它傳遞出去。
哪種方法更好呢?通常,應(yīng)該捕獲那些知道如何處理的異常,而將那些不知道怎樣處理的異常傳遞出去。如果想將異常傳遞出去,就必須在方法的首部添加一個throws說明符以便告知調(diào)用者這個方法可能會拋出異常。
仔細(xì)閱讀一下JavaAPI文檔,以便知道每個方法可能會拋出哪種異常,然后再決定是自己處理,還是添加到throws列表。對于后一種情況,也不必猶豫。將異常直接交給能夠勝任的處理器進(jìn)行處理要比壓制對它的處理更好。
同時請記住,這個規(guī)則也有一個例外。如果編寫一個覆蓋超類的方法,而這個方法又沒有拋出異常,那么這個方法就必須捕獲方法代碼中出現(xiàn)的每一個已檢查異常。不允許在子類的thrws說明符中出現(xiàn)超過超類方法所列出的異常類范圍。
假設(shè)在一個Java程序運行期間出現(xiàn)了一個錯誤。這個錯誤可能是由于文件包含了錯誤的信息,或者網(wǎng)絡(luò)連接出現(xiàn)問題造成的,也有可能是因為使用無效的數(shù)組下標(biāo),或者試圖使用一個沒有被賦值引用而造成的。用戶期望在出現(xiàn)錯誤時,程序能夠采用一些理智的行為,如果由于出現(xiàn)錯誤而使得某些操作沒有完成,程序應(yīng)該:返回到一種安全狀態(tài),并能夠讓用戶執(zhí)行一些其他的命令;或者允許用戶保存所有操作的結(jié)果,并以適當(dāng)?shù)姆绞浇K止程序。
要做到這些并不是一件很容易的事情。其原因是檢測(或引發(fā))錯誤條件的代碼通常離那些能夠讓數(shù)據(jù)恢復(fù)到安全狀態(tài),或者能夠保存用戶的操作結(jié)果,并正常地退出程序的代碼很遠(yuǎn)。異常處理的任務(wù)就是將控制權(quán)從錯誤產(chǎn)生的地方轉(zhuǎn)移給能夠處理這種情況的錯誤處理器。為了能夠在程序中處理異常情況,必須研究程序中可能會出現(xiàn)的錯誤和問題,以及哪類問題需要關(guān)注。
1.用戶輸入錯誤
除了那些不可避免的打字錄入外,有些用戶喜歡各行其是,不遵守程序的要求。例如,假設(shè)有一個用戶請求連接一個URL,而語法卻不正確。在程序代碼中應(yīng)該對此進(jìn)行檢查,如果沒有檢查,網(wǎng)絡(luò)數(shù)據(jù)包就會給出警告。
2.設(shè)備錯誤
硬件并不總是讓它做什么,它就做什么。打印機(jī)可能被關(guān)掉了。網(wǎng)頁可能臨時性地不能瀏覽。在一個任務(wù)的處理過程中,硬件經(jīng)常出現(xiàn)問題。例如,打印機(jī)在打印過程中可能沒有紙了。
3.物理限制
磁盤滿了,可用存儲空間已被用完。
4.代碼錯誤
程序方法有可能無法正確的執(zhí)行。例如,方法可能返回了一個錯誤的答案,或者錯誤地調(diào)用了其他方法。使用了一個無效的數(shù)組下標(biāo),試圖查找一個在散列表中不存在的數(shù)據(jù)項以及試圖對一個空棧進(jìn)行退棧操作。
對于方法中出現(xiàn)的錯誤,傳統(tǒng)的處理方式是返回一個特定的錯誤編碼,調(diào)用這個方法的方法對其進(jìn)行分析。例如,對于一個從文件中讀取信息的方法來說,如果返回值不是標(biāo)準(zhǔn)字符,而是一個-1,則表示文件結(jié)束。這種處理方式對于很多異常狀況都是可行的。還有一種表示錯誤狀況的常用返回值是null引用。當(dāng)希望查詢的參數(shù)不存在時,這個方法就會返回null。
遺憾的是,并不是在任何情況下都能夠返回一個錯誤編碼。有可能無法明確地將有效數(shù)據(jù)與無效數(shù)據(jù)加以區(qū)分。一個返回整型的方法就不能簡單地通過返回-1表示錯誤,因為-1很可能是一個完全合法的結(jié)果。
在Java中,如果某個方法不能夠采用正常的途徑完整它的任務(wù),就可以通過另外一個路徑退出方法。在這種情況下,方法并不返回任何值,而是拋出(throw)一個封裝了錯誤信息的對象。需要注意的是,這個方法將會立刻退出,并不返回任何值。此外,調(diào)用這個方法的代碼也將無法繼續(xù)執(zhí)行,而是,異常處理機(jī)制開始搜索能夠處理這種異常狀況的異常處理器(exceptionhandler),異常具有自己的語法和特定的繼承結(jié)構(gòu)。
如果只希望用戶能夠點擊按鈕或菜單,那幺就不需要顯式地處理鼠標(biāo)事件。鼠標(biāo)操作將由用戶界面中的各種組件內(nèi)部處理。然而,如果希望用戶使用鼠標(biāo)畫圖,就需要補(bǔ)貨鼠標(biāo)移動點擊和拖動事件。
當(dāng)用戶點擊鼠標(biāo)按鈕時,將會調(diào)用三個監(jiān)聽器方法:鼠標(biāo)第一次被按下時調(diào)用mousepressed;鼠標(biāo)被釋放時調(diào)用mousereleased;最后調(diào)用mouseclicked。如果只對最終的點擊事件感興趣,就可以忽略前兩個方法。用mouseevent類對象作為參數(shù),調(diào)用getX和gety方法可以獲得鼠標(biāo)被按下時鼠標(biāo)指針?biāo)诘膞和y坐標(biāo)。要想?yún)^(qū)分單擊,雙擊和三擊,需要使用getclickcount方法。
有些用戶界面設(shè)計者喜歡讓用戶采用鼠標(biāo)點擊與鍵盤修飾符組合(例如,control+shift+click)的方式進(jìn)行操作。我們感覺這并不是一種值得贊許的方式。如果對此持有不同的觀點,可以看一看同時檢測鼠標(biāo)按鍵和鍵盤修飾符所帶來的混亂。
需要注意,在Windows環(huán)境下,使用BUTTON3_DOWN_MASK檢測鼠標(biāo)右鍵(非主要的)狀態(tài)。
當(dāng)鼠標(biāo)在窗口上移動時,窗口將會收到一連串的鼠標(biāo)移動事件。請注意:有兩個獨立的接口mouseListener和mouseMotionListener。這樣做有利于提高效率。當(dāng)用戶移動鼠標(biāo)時,只關(guān)心鼠標(biāo)點擊(clicks)的監(jiān)聽器就不會被多余的鼠標(biāo)移動(moves)所困擾。
通常,激活一個命令可以有多種方式,用戶可以通過菜單、擊鍵或工具欄上的按鈕選擇特定的功能。在AWT事件模型中實現(xiàn)這些非常容易:將所有事件 連接到同一個監(jiān)聽器上。例如:假設(shè)blueAction是一個動作監(jiān)聽器,它的actionPerformed方法可以將背景顏色改變成藍(lán)色。將一個監(jiān)聽 器對象加到下面幾個事件源上:
·標(biāo)記為Blue的工具欄按鈕
·標(biāo)記為Blue的菜單項
·擊鍵CTRL+B
然后,無論改變背景顏色的命令是通過哪種方式下達(dá)的,是點擊按鈕、菜單選擇,還是按下鍵盤,其操作動作都是一樣的。
Swing包提供了一種非常實用的機(jī)制來封裝命令,并將它們連接到多個事件源,這就是Action接口。一個動作是一個封裝下列內(nèi)容的對象:
·命令的說明(一個文本字符串和一個可選圖標(biāo));
執(zhí)行命令所需要的參數(shù)(例如,在列舉的例子中請求改變的顏色)。
第一個方法是ActionListener接口中很熟悉的一個:實際上,Action接口擴(kuò)展于ActionListener接口,因此,可以在任何需要ActionListener對象的地方使用Action對象。
接下來的兩個方法允許啟用或禁用這個動作,并檢查這個動作當(dāng)前是否啟用。當(dāng)一個連接到菜單或工具欄上的動作被禁用時,這個選項就會變成灰色。
putValue和getvalue方法允許存儲和檢索動作對象中的任意名/值。有兩個重要的預(yù)定義字符串:Action.NAME和Action.sMALLjcON,用于將動作的名字和圖標(biāo)存儲到一個動作對象中。
如果動作對象添加到菜單或工具欄上,它的名稱和圖標(biāo)就會被自動地提取出來,并顯示在菜單項或工具欄中。SHORT_DESCRiRTION值變成了工具提示。
Action接口的最后兩個方法能夠讓其他對象在動作對象的屬性發(fā)生變化時得到通告,尤其是菜單或工具欄處罰的動作。例如,如果增加一個菜單,作為動作 對象的屬性變更監(jiān)聽器,而這個動作對象隨后被禁用,菜單就會被調(diào)用,并將動作名稱變?yōu)榛疑?。屬性變更監(jiān)聽器是一種常用的構(gòu)造形式,它是JavaBeans 組件模型的一部分。
需要注意,Action一個接口,而不是一個類。實現(xiàn)這個接口的所有類都必須實 現(xiàn)剛才討論的7個方法。慶幸的是,有一個類實現(xiàn)了這個接口除actionPerformed方法之外的所有方法,它就是AbstractAction個類 存儲了所有名/值對,并管理著屬性變更監(jiān)聽器。我們可以直接擴(kuò)展AbstractAction類,并在擴(kuò)展類中實現(xiàn)actionPerformed方法。
構(gòu)造器讀取動作的名稱和圖標(biāo),為工具提示設(shè)置簡要說明,將工作設(shè)置為監(jiān)聽器。
最后,想要將這個動作對象添加到擊鍵中,以便讓用戶敲擊鍵盤命令來執(zhí)行這項動作。為了將動作與擊鍵關(guān)聯(lián)起來,首先需要生成KeyStroke類對象。這 是一個很有用的類,它封裝了對鍵的說明。要想生成一個Keystroke對象不要調(diào)用構(gòu)造器,而是調(diào)用KeyStroke類中的靜態(tài) getKeyStroke方法:
為了能夠理解下一個步驟,需要知道keyboardfocus的概 念。用戶界面中可以包含許多按鈕、菜單、滾動欄以及其他的組件。當(dāng)用戶敲擊鍵盤時,這個動作會被發(fā)送給擁有焦點的組件。通常具有焦點的組件可以明顯地察覺 到(但并不總是這樣),例如,在Java觀感中,具有焦點的按鈕在按鈕文本周圍有一個細(xì)的矩形邊框。用戶可以使用TAB鍵在組件之間移動焦點。當(dāng)按下 SPACE鍵時,就點擊了擁有焦點的按鈕。還有一些鍵執(zhí)行一些其他的動作,例如,按下箭頭鍵可以移動滾動條。
然而,在這里的示例中,并不希望將擊鍵發(fā)送給擁有焦點的組件。否則,每個按鈕都需要知道如何處理CTRL+Y、CTRL+B和CTRL+R這些組合鍵。
這是一個常見的問題,Swing設(shè)計者給出了一種很便捷的解決方案。每個JComponent有三個輸入映射(imput maps),每一個映射的KeyStroke對象都與動作關(guān)聯(lián)。
對于圖形用戶界面的程序來說,事件處理是十分重要的。要想實現(xiàn)用戶界面,必須掌握J(rèn)ava事件處理的基本方法。
任何支持GUI的操作環(huán)境都要不斷地監(jiān)視敲擊鍵盤或點擊鼠標(biāo)這樣的事件。操作環(huán)境將這些事件報告給正在運行的應(yīng)用程序。如果有事件產(chǎn)生,每個應(yīng)用程序?qū)? 決定如何對它們作出響應(yīng)。在VisualBasic這樣的語言中,事件與代碼之間有著明確的對應(yīng)關(guān)系。程序員對相關(guān)的特定事件編寫代碼,并將這些代碼放置 在過程中,通常人們將它們稱為事件過程(event procedure)。例如,有一個名為HelpButton的VisualBasic按鈕有一個與之關(guān)聯(lián)的HelpButton_Click時間過程。 這個過程中的代碼將在點擊按鈕后執(zhí)行。每個VisualBasic的GUI組件都響應(yīng)一個固定的事件集,不可能改變VisualBasic組件響應(yīng)的事件 集。
另一方面,如果使用像原始的C這樣的語言進(jìn)行事件驅(qū)動的程序設(shè)計,那就需要編寫代碼來 不斷地檢查事件隊列,以便查詢操作環(huán)境報告的內(nèi)容(通常這些代碼被放置在包含很多switch語句的循環(huán)體申)。顯然,這種方式編寫的程序可讀性很差,而 且在有些情況下,編碼的難度也非常大。它的好處在于響應(yīng)的事件不受限制,而不像VisualBasic這樣的語言,將事件隊列對程序員隱藏起來。
Java程序設(shè)計環(huán)境折中了VisualBasic與原始C的事件處理方式,因此,它既有著強(qiáng)大的功能,又具有一定的復(fù)雜性。在AWT所知的事件范圍 內(nèi),完全可以控制事件從事件源(event source)例如,按鈕或滾動條,到事件監(jiān)聽器(event listener)的傳遞過程,并將任何對象指派給事件監(jiān)聽器。不過事實上,應(yīng)該選擇一個能夠便于響應(yīng)事件的對象。這種事件委托模型(event delegation model)與VisualBasic那種預(yù)定義監(jiān)聽器模型比較起來更加靈活。
事件源有一些向其注冊事件監(jiān)聽器的方法。當(dāng)某個事件源產(chǎn)生事件時,事件源會向為事件注冊的所有事件監(jiān)聽器對象發(fā)送一個通告。
像Java這樣的面向?qū)ο笳Z言,都將事件的相關(guān)信息封裝在一個事件對象(event object)中,在Java中,所有的事件對象都最終派生于java.util.EventObject類。當(dāng)然,每個事件類型還有子類,例 如,ActionEvent和WindowEvent。
不同的事件源可以產(chǎn)生不同類別的事件。例如,按鈕可以發(fā)送一個ActionEvent對象,而窗扣可以發(fā)送WindowEvent對象。
綜上所述,下面給出AWT事件處理機(jī)制的概要:
監(jiān)聽器對象是一個實現(xiàn)了特定監(jiān)聽器接口(listener interface)的類的實例。
事件源是一個能夠注冊監(jiān)聽器對象并發(fā)送事件對象的對象。
當(dāng)事件發(fā)生時,事件源將事件對象傳遞給所有注冊的監(jiān)聽器。
監(jiān)聽器對象將利用事件對象中的信息決定如何對事件做出響應(yīng)。
當(dāng)前題目:【建站知識】網(wǎng)站建設(shè)程序異常事件
URL地址:http://www.rwnh.cn/news/165927.html
網(wǎng)站建設(shè)、網(wǎng)絡(luò)推廣公司-創(chuàng)新互聯(lián),是專注品牌與效果的網(wǎng)站制作,網(wǎng)絡(luò)營銷seo公司;服務(wù)項目有網(wǎng)站建設(shè)等
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容