NullPointerException是一个运行时异常的可能原因是每个方法都可能抛出它,所以每个方法都需要有"throws NullPointerException",这样很丑陋。但是远程异常(RemoteException)就是这种情况。
而远程异常不是运行时异常的可能原因是告诉客户端如何处理该异常。但在远程环境中,每个方法都需要抛出它,所以和抛出NullPointerException没有区别。
猜测?我表达清楚了吗?
NullPointerException是一个运行时异常的可能原因是每个方法都可能抛出它,所以每个方法都需要有"throws NullPointerException",这样很丑陋。但是远程异常(RemoteException)就是这种情况。
而远程异常不是运行时异常的可能原因是告诉客户端如何处理该异常。但在远程环境中,每个方法都需要抛出它,所以和抛出NullPointerException没有区别。
猜测?我表达清楚了吗?
我不会讨论这个决定,我只引用Ann Wollrath(领导Java RMI的设计和实现)对此决定的解释。这是从RMI-USERS档案中摘取的信息(来自1999年1月的消息):
将RemoteException作为已检查异常并要求远程方法在其throws子句中列出该异常的决定并不是一个涉及信仰的决定。而是基于如何使分布式计算可靠的考虑。这个问题偶尔会在我们用户列表上出现。我有一个详细的回复,我曾经发表过。如果你感兴趣,下面是我的回复。我在rmi-users档案中找不到它,因此我在下面附上了它。
祝好!
-- Ann
我想解释一下将RemoteException作为Checked Exception而不是RuntimeException的基本原理。
1)网络不可靠
很遗憾,每个网络都会出现短暂的故障,即使您可以建立网络冗余,大多数网络也没有这样做。因特网和内部网络都有短暂的故障,所以每个RPC调用都可能失败。故障类型可能与“网络”本身无关;如果服务器没有文件描述符了,客户端将获得连接异常。这不是网络故障,而是服务器处于资源匮乏的瞬态状态。
RMI并非仅设计处理整个网络在单台计算机崩溃时的情况。这样的网络被认为是可靠的,要么所有内容正常运行,要么全部停止--不存在部分故障。RMI的目标是面向更广泛的受众。
2)RPC失败不能对客户端隐藏
部分故障是分布式编程的事实,这些故障无法隐藏到程序中。失败会在客户端中显示,无论是已检查的异常还是未检查的异常,它仍然会显示在客户端。那么,应该如何向客户端指示此类故障?
3)已检查的异常促进了更健壮的程序
曾经的Java版本没有已检查的异常,而异常处理是建议性的,这是一个不安全的世界。Jim Waldo和我特别建议编译器检查异常。Jim在他的论点中非常有说服力,讲述了健壮代码将统治的世界。在考虑一番后,Java被重新设计为拥有已检查的异常。只有那些没有恢复或反映应用程序错误的异常将不被检查(例如OutOfMemoryError、NullPointerException)。世界再次变得安全。
当Java API和编译器中许多异常从未检查过改为已检查时,Java工程师惊讶地发现,编译器强制执行区分时,他们发现了实现中的漏洞!因此,处理错误条件的最佳努力,无论意图多么良好,都不够好。编译器对某些事情很有用:-)
4)RemoteException应该是已检查的异常
既然远程调用中存在RemoteException(请参见#1,#2),而已检查的异常可以强制您编写安全代码(#3),因此我们认为将RemoteException作为已检查的异常是一个好主意。编写健壮的分布式程序已经足够困难,无需编译器来帮助您处理异常。
因此,有人可能会认为RemoteException类似于OutOfMemoryError;如果远程调用失败,则您的程序应该崩溃死亡。我不同意这一点。是的,在某些情况下,没有从RemoteException中恢复;但是,如果您正在编写可靠的分布式程序,则客户端需要捕获故障并适当地重试。也许您需要与另一个服务器联系或终止某种事务。如果未处理RemoteException,它将上升并崩溃客户端(呕吐)。
其他人曾经说过,有些远程接口在本地情况和远程情况下都被使用,客户端不应该在本地情况下处理异常,因此不需要在throws子句中包含RemoteException并且还不需要强制处理它。现在
-- Ann Wollrath
NullPointerException
比RemoteException
更有潜在的风险。 几乎任何调用对象方法的Java代码都可能抛出NullPointerException
。 只有RMI代码才能抛出RemoteException
,这只是“所有代码”的微小子集。
在编写RMI库时,设计人员决定让客户端代码期望处理这些异常。考虑到远程代码执行的本质,我认为这是合理的。
NullPointerException
是一个RuntimeException
。 - MatthewRemoteException
仅适用于来自java.rmi
和javax.rmi
包(及其子包)的代码之外,RemoteException
是IOException
的一种类型,就像SocketException
一样...而且所有的IOException
都是已检查异常。IOException
的子类。IOException
(以及任何其他从 Exception
而不是 RuntimeException
继承的类)是一个受检查的异常,因此任何继承自它的类也是受检查异常。 - Powerlord