簡體   English   中英

為什么NullPointerException是運行時異常而RemoteException不是?

[英]Why NullPointerException is a runtime exception and RemoteException not?

可能的原因是因為NullPointerException是一個運行時異常是因為每個方法都可以拋出它,因此每個方法都需要“拋出NullPointerException”,並且會很難看。 但這會發生在RemoteException上。

並且可能的原因是因為RemoteException不是運行時異常,就是告訴客戶端處理異常。 但是遠程環境中的每個方法都需要拋出它,因此拋出NullPointerException沒有區別。

猜測? 我清楚了嗎?

我不會討論這個決定,我只是引用Ann Wollrath(他領導Java RMI的設計和實現)的決定的解釋。 這是從RMI-USERS檔案中的這條消息中提取的(1999年1月的消息):

將RemoteException作為一個已檢查的異常並要求遠程方法在其throws子句中列出異常的決定並不是宗教性的。 該決定基於如何使分布式計算可靠。 這個問題偶爾出現在我們的用戶列表中。 我剛才發布了一個詳細的回復。 如果您有興趣,請點擊這里。 我在rmi-users存檔中找不到它,所以我將其包含在下面。

干杯,

- 安


我想解決使RemoteException成為檢查異常而不是RuntimeException的基本原理。

1)網絡不可靠

我希望他們是,但事實上,他們不是。 每個網絡都有短暫的故障。 您可以構建網絡冗余,但事實是大多數網絡都沒有。 內聯網有短暫的故障,互聯網也是如此。 因此,每個RPC都會出現故障。 失敗的類型本身可能與“網絡”無關; 如果您的服務器用完文件描述符,您的客戶端將獲得連接異常。 從網絡被破壞的意義上講,這不是網絡故障; 您的服務器處於資源匱乏的暫時狀態。

RMI的目的不僅僅是處理單個機器崩潰時整個網絡崩潰的有限情況。 這樣的網絡將被認為是可靠的,無論是一切都結束還是一切都失敗了 - 沒有部分失敗。 RMI針對更廣泛的受眾。

2)無法從客戶端隱藏RPC故障

部分失敗是分布式編程的事實; 這些失敗不能隱藏到程序中。 客戶端出現故障,無論是檢查異常還是未檢查異常,它仍會顯示出來。 那么,如何向客戶表明這種失敗?

3)檢查異常可以培養更強大的程序

有一段時間,Oak和最早的Java版本沒有檢查異常。 異常處理是建議性的,這是一個不安全的世界。 我們的小組(Jim Waldo和我特別是:-)建議編譯器檢查異常。 吉姆在他的論點中非常有說服力,講述了一個強大的代碼將占據統治地位的世界。 經過一番考慮后,Java被重組以檢查異常。 只有那些沒有恢復或反映應用程序錯誤的異常才會被取消選中(例如,分別為OutOfMemoryError,NullPointerException)。 世界再次安全。

想象一下,當Java API和編譯器中的許多異常從未經檢查變為檢查時,Java工程師會感到驚訝,並且編譯器強制執行區分,他們發現了實現中的錯誤! 因此,處理錯誤條件的最佳努力,無論出於好意,都不夠好。 那個編譯器對某些東西很有用:-)

4)RemoteException應該是一個經過檢查的異常

好的,所以回到正軌。 由於RemoteException在RPC調用中是生命中的事實(參見#1,#2),並且檢查了異常強制您編寫安全代碼(#3),我們認為將RemoteException作為已檢查的異常是一個好主意。 編寫健壯的分布式程序是很困難的,沒有編譯器可以幫助您處理異常。

因此,有些人可能認為RemoteException就像OutOfMemoryError; 如果遠程呼叫失敗,你的程序應該會死掉。 我不同意這一點。 是的,在某些情況下,RemoteException無法恢復; 但是如果您正在編寫可靠的分布式程序,那么您的客戶端需要捕獲故障並進行適當的重試。 也許您需要聯系其他服務器,或中止某種事務。 如果未處理RemoteException,它將滲透並崩潰您的客戶端(yuk)。

其他人已經聲明在本地案例和遠程案例中都使用了一些遠程接口,並且客戶端不應該在本地案例中處理異常,因此RemoteException不應該在throws子句和處理中它不應該是強制性的。 現在,如果我們允許遠程接口方法省略RemoteException並且有一個“rmic”開關來生成會拋出未經檢查的RemoteException的存根,那么客戶端沒有選擇。 異常處理的決定應保留在客戶端。 如果定義一個僅拋出未經檢查的異常的接口,則永遠不能編寫希望編譯器幫助處理這些異常的客戶端。 我們已經從上面的例子中看到,檢查異常會產生健壯的代碼。

另一個突然出現的問題是,開發人員需要簡單地翻譯本地接口並將其用作遠程接口。 這可能適用於一小部分情況,但如果接口的設計並未考慮並發性和部分故障以及呼叫延遲,則接口捕獲的協議可能不適合在分布式情況下使用。 是否在這些操作中傳遞了足夠的信息以使操作具有冪等性? 也許,但很可能不是。

將RemoteException放在每個throws子句中可能看起來很痛苦,但是編寫健壯的分布式應用程序需要付出代價。

- Ann Wollrath

NullPointerExceptionRemoteException有更多的可能性。 任何調用對象上的方法的代碼(實際上幾乎都是任何Java代碼)都可能拋出NullPointerException 只有RMI代碼才能拋出RemoteException 這是“所有代碼”的一小部分。

在編寫RMI庫時,設計人員決定使客戶端代碼期望處理這些異常。 考慮到遠程代碼執行的性質,我認為這是合理的。

我理解的方式是:

  • 對於可以阻止的事情,拋出RuntimeExceptions。
  • 對於那些不可避免但可以恢復的事情,會拋出例外情況
  • 對於那些不可避免且無法恢復的事情,會拋出錯誤。

例如,始終可以避免NullPointerExceptions,因此是未經檢查的異常。 當網絡出現故障時可能會發生RemoteException,這在方法調用之前無法合理地阻止,因此會被檢查。

除了僅應用於java.rmijavax.rmi包(及其子包)中的代碼的RemoteException之外, RemoteException是一種IOException ,就像SocketException是......並且所有IOException都是經過檢查的異常。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM