<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    愛睡覺的小耗子
    ——等待飄雪的日子...努力,努力,再努力!
    posts - 9,  comments - 33,  trackbacks - 0
    轉(zhuǎn)載于:http://www.tangrui.net/2007/01/09/difference-between-java-and-dotnet-on-exception-handling/
     
    關(guān)于 Java 和 .Net 優(yōu)劣的爭(zhēng)論一直在繼續(xù),而在異常處理方面體現(xiàn)得最為激烈,因?yàn)樗麄冎g的差異是如此明顯。.Net 晚于 Java 出現(xiàn),那么 Java 對(duì) .Net 就理應(yīng)起到很重要的借鑒作用,但是偉大的 Anders Hejlsberg 為什么沒有繼續(xù) Java 的實(shí)現(xiàn)方式,而是另辟蹊徑,這是一個(gè)非常值得研究的問題。因?yàn)槲覀円姓J(rèn)一個(gè)真理:正確的東西大家都是一樣的正確,錯(cuò)誤的卻各有個(gè)的錯(cuò)誤。可以肯定這不可 能是 Anders 的疏忽,那么他的道理究竟何在,或者說他們之間究竟有什么區(qū)別?

          在你能耐下心來看完這篇帖子之前,我想要明確告訴你一個(gè)結(jié)論:Java 和 .Net 在異常處理的本質(zhì)上是沒有區(qū)別的。

    一、Java 是如何處理異常的

          如果一個(gè) Java 方法要拋出異常,那么需要在這個(gè)方法后面用 throws 關(guān)鍵字定義可以拋出的異常類型。倘若沒有定義,就認(rèn)為該方法不拋出任何異常。如果從方法的入口和出口的角度去考慮一下這個(gè)規(guī)范,我們知道參數(shù)可以認(rèn)為是方 法的入口(當(dāng)然某些情況下也可以是出口),而返回值則是方法的出口,這是在程序正常執(zhí)行的情況下,數(shù)據(jù)從入口入,出口出。要是程序非正常執(zhí)行,產(chǎn)生異常又 當(dāng)如何? 被拋出的異常應(yīng)該如何從方法中釋放出來呢? Java 的這種語法規(guī)范就如同給異常開了一個(gè)后門,讓異常可以堂而皇之“正確”地從方法里被拋出。

          這樣的規(guī)范決定了 Java 語法必須強(qiáng)行對(duì)異常進(jìn)行 try-catch。設(shè)想一下,對(duì)于以下的方法簽名:

    public void foo() throws BarException { ... }

    暗含了兩方面的意思:第一,該方法要拋出 BarException 類型的異常;第二,除了 BarException 外不能拋出其他的異常。而正是這第二點(diǎn)的緣故,我們要如何保證沒有除 BarException 之外的任何異常被拋出呢? 很顯然,就需要 try-catch 其他的異常。也就是說,一般情況下,方法不拋出哪些異常就要在方法內(nèi)部 try-catch 這些異常。

          Java 這樣的機(jī)制既有優(yōu)點(diǎn),也有缺點(diǎn)。先來說說優(yōu)點(diǎn):

    • 很顯然,這種規(guī)范是由 Java 編譯器決定的。倘若 Java 程序的入口點(diǎn) main() 方法沒有任何異常拋出,就是說要在 main() 方法內(nèi)部,即整個(gè)程序內(nèi)部捕捉所有的異常,否則將無法通過編譯。這樣編譯器保證了程序?qū)γ總€(gè)異常都有相應(yīng)的計(jì)劃和處理,不會(huì)有未處理的異常被泄露到虛擬機(jī) 中,導(dǎo)致程序意外中斷或退出,也就是增強(qiáng)了程序的健壯性。當(dāng)然,Java 有 RuntimeException 的概念,這樣的異常仍然可以隨時(shí)被拋出到虛擬機(jī)中。
    • 強(qiáng)行 try-catch 要求把異常作為程序設(shè)計(jì)的一部分看待。就如同方法的參數(shù)和返回值一樣,在編寫一個(gè)方法時(shí),要結(jié)合上下文做出通盤的考慮和打算。雖然異常是所謂的“意外情況”,但是這些“例外”理應(yīng)是被我們?nèi)苛私獠⑻幚淼摹?/li>
    • 方便調(diào)試。異常理應(yīng)在正確的位置被捕捉。當(dāng)異常發(fā)生時(shí),我們能更清楚的了解到其來源和相應(yīng)處理程序的位置,而免去了在整個(gè)調(diào)用棧中摸索的麻煩。
    • 在不借助任何文檔的情況下,從方法簽名就可以知曉應(yīng)該對(duì)哪些異常進(jìn)行處理。

          Java 異常處理機(jī)制的這些優(yōu)點(diǎn)也直接導(dǎo)致了他的致命弱點(diǎn):將程序變得異常繁復(fù)。往往一個(gè)簡(jiǎn)單的程序,功能代碼寥寥幾行,而異常處理部分卻占用了程序的絕大部分篇 幅;同時(shí)導(dǎo)致縮進(jìn)深度加深,既不利于書寫,也不利于閱讀。另外他的強(qiáng)行 try-catch 需要程序員有更高深的造詣,能夠通盤考慮異常處理設(shè)計(jì)問題,這個(gè)在程序開始之初或者對(duì)于初學(xué)者是一個(gè)不小的門檻。這往往會(huì)阻礙其推廣與發(fā)展,因?yàn)榈退匠? 學(xué)者的信心往往因此而受到打擊。然而對(duì)于高手來說,編譯器是否能幫助他們找到未被處理的異常只是一個(gè)方便與否的問題,只要在編寫方法時(shí)注意了異常處理,即 便沒有編譯器的支持,情況也不會(huì)糟糕太多。反而倒是由于要遵循這樣復(fù)雜的異常處理規(guī)范,以至于大多數(shù)人都可能為了圖一時(shí)方便,對(duì)異常的基類型 Exception 或 Throwable 進(jìn)行籠統(tǒng)地捕捉,這樣做的危害就是那些你無法處理的異常被溺死在處理程序中,(按照異常處理原則,我們應(yīng)該只捕捉那些可以被處理或恢復(fù)的異常,而把其他的 異常繼續(xù)拋出。至于這樣做的優(yōu)勢(shì),以及不這樣做所帶來的問題,不是一兩句能夠說清楚,這里就不展開討論了。)導(dǎo)致程序的不穩(wěn)定和不確定。既沒有發(fā)揮 Java 語法在這方面的優(yōu)勢(shì),反而增加了憂患。

    二、.Net 是如何處理異常的

          一句話概括 .Net 的異常處理方式就是隨心所欲。沒有人要求你一定要拋出異常,也更沒有人要求你一定要捕捉異常。未被捕捉的異常會(huì)被以 Unhandled Exception 的形式拋出到虛擬機(jī)中。在此我就要先解決一下文章開頭提到的問題,為什么說 Java 和 .Net 這兩種異常處理機(jī)制在本質(zhì)上是相同的。可以從兩個(gè)方面來考慮:

    1. 默認(rèn)情況下。Java 在默認(rèn)情況下 main() 方法是不拋出異常的,正如前面所說的,這要求所有的異常都必須在 main() 方法內(nèi)部被捕捉;而 .Net 則沒有這種約束,他的 Main() 以至于整個(gè)應(yīng)用程序中的任何一個(gè)方法對(duì)異常都是完全開放的。這樣來看,這兩者剛好是對(duì)立互補(bǔ)的。
    2. 非默認(rèn)情況下。Java 可以通過在 main() 方法后面加 throws 關(guān)鍵字使得整個(gè)應(yīng)用程序?qū)Ξ惓i_放;而 .Net 則可以通過給應(yīng)用程序域(Application Domain)的 UnhandledException 事件添加委托達(dá)到捕捉所有異常的目的,很顯然這又是對(duì)立互補(bǔ)的。

    因此,就好像一個(gè)是“正反”,一個(gè)是“反正”,加在一起“正反反正”都是一樣的,對(duì)于達(dá)到控制異常的目錄來說,是沒有區(qū)別的。

          很多 Java 愛好者都鄙視 .Net 的這種行為,一方面他令程序變得不夠健壯,因?yàn)槟J(rèn)情況下沒有強(qiáng)制的辦法要求所有的異常都被處理,或被正確處理;另外,他為調(diào)試增加了困難,不借助文檔或 代碼你將無法了解到一個(gè)方法可能拋出什么異常,而當(dāng)一個(gè)異常被拋出的時(shí)候,同時(shí)異常處理代碼又寫得不夠完善,你將不得不仔細(xì)查看整個(gè)調(diào)用棧來確定異常出現(xiàn) 的位置,而對(duì)于這一點(diǎn) Java 默認(rèn)是強(qiáng)制的。

          但是 Anders 的想法總是有道理的。

    1. .Net 代碼寫起來非常容易。這是對(duì)于初學(xué)者,或者那些只是想實(shí)現(xiàn)一些測(cè)試性小功能的人而言,你完全沒有必要考慮太多異常處理的細(xì)節(jié),你要的就是寫代碼,然后讓他 跑起來。這樣的簡(jiǎn)單性無疑是你希望看到的,這樣的簡(jiǎn)單性無疑更有利于 .Net 在市場(chǎng)上的推廣。由于他在這方面并沒有什么理論上的漏洞,也就仍然適合構(gòu)建龐大的項(xiàng)目,只是感覺沒有那么舒服罷了。
    2. 一定程度上增加了程序的安全性。難道不捕捉異常可以被成為是安全的嗎?這個(gè)話也許要從另外一方面來想,前面說過,有些 Java 程序員(絕對(duì)不占少數(shù))為了圖省事,在強(qiáng)行捕捉異常的壓迫下,選擇捕捉異常的基類型,也就是捕捉所有的異常。這樣當(dāng)有你無法處理的異常出現(xiàn)時(shí),他們就溺死 在了你的代碼中,而外面的程序全然不知,還在以一種不確定的狀態(tài)運(yùn)行著,這就可能是危險(xiǎn)的開始。而如果是 .Net,那么 Unhandled Exception 會(huì)被虛擬機(jī)捕獲,導(dǎo)致程序異常退出,雖然這從面子上對(duì)于用戶不是一個(gè)好的交代,但是深層次地他避免了程序在危險(xiǎn)的狀態(tài)下繼續(xù)運(yùn)行。

          總之,蘿卜白菜各有所愛。我的這篇帖子力求公正地討論了這個(gè)問題,希望能對(duì)你有所幫助。

    posted on 2007-12-03 10:17 Harriet 閱讀(1066) 評(píng)論(1)  編輯  收藏 所屬分類: Java

    FeedBack:
    # re: Java 和 .Net 在異常處理機(jī)制上的區(qū)別
    2008-07-04 15:17 | 笑笑江南


    能不能把文章簡(jiǎn)化成這樣:
    這樣當(dāng)有你無法處理的異常出現(xiàn)時(shí),他們就溺死 在了你的代碼中,而外面的程序全然不知,還在以一種不確定的狀態(tài)運(yùn)行著,這就可能是危險(xiǎn)的開始。而如果是 .Net,那么 Unhandled Exception 會(huì)被虛擬機(jī)捕獲,導(dǎo)致程序異常退出,雖然這從面子上對(duì)于用戶不是一個(gè)好的交代,但是深層次地他避免了程序在危險(xiǎn)的狀態(tài)下繼續(xù)運(yùn)行。   回復(fù)  更多評(píng)論
      

    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     

    公 告

    心要沉下去,思緒才會(huì)浮上來,水平也就上來了


    <2007年12月>
    2526272829301
    2345678
    9101112131415
    16171819202122
    23242526272829
    303112345

    常用鏈接

    留言簿(2)

    隨筆分類

    隨筆檔案

    文章檔案

    相冊(cè)

    搜索

    •  

    積分與排名

    • 積分 - 86214
    • 排名 - 669

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 亚洲?v无码国产在丝袜线观看| 久久午夜夜伦鲁鲁片免费无码 | 亚洲高清美女一区二区三区| 国产成人1024精品免费| 亚洲一区二区三区在线播放| 一区二区三区免费看| 亚洲无线一二三四区手机| 中文字幕免费在线观看动作大片 | 亚洲精品无码不卡在线播放HE| 免费的黄色的网站| 国产乱辈通伦影片在线播放亚洲| 波霸在线精品视频免费观看| 亚洲日韩欧洲乱码AV夜夜摸| 久久国产乱子伦精品免费看| 亚洲同性男gay网站在线观看| 在线v片免费观看视频| 久久亚洲AV成人无码国产电影| 免费在线观看日韩| 国产裸体美女永久免费无遮挡| 亚洲va久久久噜噜噜久久狠狠| 99热免费在线观看| 亚洲最大av资源站无码av网址| 国产小视频在线免费| 一级毛片a免费播放王色| 亚洲av无码乱码国产精品| 免费A级毛片无码A∨免费| 亚洲国产av玩弄放荡人妇| 亚洲愉拍99热成人精品热久久 | 成人毛片18女人毛片免费96| 相泽南亚洲一区二区在线播放| 国产精品亚洲不卡一区二区三区| 午夜理伦剧场免费| 亚洲国产区男人本色| 亚洲精品自产拍在线观看| 免费精品国产日韩热久久| 美美女高清毛片视频黄的一免费 | 456亚洲人成影院在线观| 亚洲av无码国产精品色在线看不卡| 国产免费一区二区三区在线观看| 亚洲熟妇无码一区二区三区导航| 国产亚洲精品久久久久秋霞|