JAVA和.NET异常的区别
关于 Java 和 .Net
优劣的争论一直在继续,而在异常处理方面体现得最为激烈,因为他们之间的差异是如此明显。.Net
晚于 Java 出现,那么 Java 对 .Net
就理应起到很重要的借鉴作用,但是伟大的 Anders Hejlsberg
为什么没有继续 Java
的实现方式,而是另辟蹊径,这是一个非常值得研究的问题。因为我们要承认一个真理:正确的东西大家都是一样的正确,错误的却各有个的错误。可以肯定这不可能是
Anders
的疏忽,那么他的道理究竟何在,或者说他们之间究竟有什么区别?
在你能耐下心来看完这篇帖子之前,我想要明确告诉你一个结论:Java
和 .Net 在异常处理的本质上是没有区别的。
一、Java
是如何处理异常的
如果一个
Java 方法要抛出异常,那么需要在这个方法后面用 throws
关键字定义可以抛出的异常类型。倘若没有定义,就认为该方法不抛出任何异常。如果从方法的入口和出口的角度去考虑一下这个规范,我们知道参数可以认为是方法的入口(当然某些情况下也可以是出口),而返回值则是方法的出口,这是在程序正常执行的情况下,数据从入口入,出口出。要是程序非正常执行,产生异常又当如何?
被抛出的异常应该如何从方法中释放出来呢? Java
的这种语法规范就如同给异常开了一个后门,让异常可以堂而皇之“正确”地从方法里被抛出。
这样的规范决定了
Java 语法必须强行对异常进行
try-catch。设想一下,对于以下的方法签名:
public void foo() throws BarException { ... }
暗含了两方面的意思:第一,该方法要抛出 BarException
类型的异常;第二,除了 BarException
外不能抛出其他的异常。而正是这第二点的缘故,我们要如何保证没有除
BarException 之外的任何异常被抛出呢? 很显然,就需要 try-catch
其他的异常。也就是说,一般情况下,方法不抛出哪些异常就要在方法内部
try-catch 这些异常。
Java
这样的机制既有优点,也有缺点。先来说说优点:
- 很显然,这种规范是由 Java 编译器决定的。倘若 Java 程序的入口点
main() 方法没有任何异常抛出,就是说要在 main()
方法内部,即整个程序内部捕捉所有的异常,否则将无法通过编译。这样编译器保证了程序对每个异常都有相应的计划和处理,不会有未处理的异常被泄露到虚拟机中,导致程序意外中断或退出,也就是增强了程序的健壮性。当然,Java
有 RuntimeException
的概念,这样的异常仍然可以随时被抛出到虚拟机中。
- 强行 try-catch
要求把异常作为程序设计的一部分看待。就如同方法的参数和返回值一样,在编写一个方法时,要结合上下文做出通盘的考虑和打算。虽然异常是所谓的“意外情况”,但是这些“例外”理应是被我们全部了解并处理的。
-
方便调试。异常理应在正确的位置被捕捉。当异常发生时,我们能更清楚的了解到其来源和相应处理程序的位置,而免去了在整个调用栈中摸索的麻烦。
-
在不借助任何文档的情况下,从方法签名就可以知晓应该对哪些异常进行处理。
Java
异常处理机制的这些优点也直接导致了他的致命弱点:将程序变得异常繁复。往往一个简单的程序,功能代码寥寥几行,而异常处理部分却占用了程序的绝大部分篇幅;同时导致缩进深度加深,既不利于书写,也不利于阅读。另外他的强行
try-catch
需要程序员有更高深的造诣,能够通盘考虑异常处理设计问题,这个在程序开始之初或者对于初学者是一个不小的门槛。这往往会阻碍其推广与发展,因为低水平初学者的信心往往因此而受到打击。然而对于高手来说,编译器是否能帮助他们找到未被处理的异常只是一个方便与否的问题,只要在编写方法时注意了异常处理,即便没有编译器的支持,情况也不会糟糕太多。反而倒是由于要遵循这样复杂的异常处理规范,以至于大多数人都可能为了图一时方便,对异常的基类型
Exception 或 Throwable
进行笼统地捕捉,这样做的危害就是那些你无法处理的异常被溺死在处理程序中,(按照异常处理原则,我们应该只捕捉那些可以被处理或恢复的异常,而把其他的异常继续抛出。至于这样做的优势,以及不这样做所带来的问题,不是一两句能够说清楚,这里就不展开讨论了。)导致程序的不稳定和不确定。既没有发挥
Java 语法在这方面的优势,反而增加了忧患。
二、.Net
是如何处理异常的
一句话概括
.Net
的异常处理方式就是随心所欲。没有人要求你一定要抛出异常,也更没有人要求你一定要捕捉异常。未被捕捉的异常会被以
Unhandled Exception
的形式抛出到虚拟机中。在此我就要先解决一下文章开头提到的问题,为什么说
Java 和 .Net
这两种异常处理机制在本质上是相同的。可以从两个方面来考虑:
- 默认情况下。Java 在默认情况下 main()
方法是不抛出异常的,正如前面所说的,这要求所有的异常都必须在 main()
方法内部被捕捉;而 .Net 则没有这种约束,他的 Main()
以至于整个应用程序中的任何一个方法对异常都是完全开放的。这样来看,这两者刚好是对立互补的。
- 非默认情况下。Java 可以通过在 main() 方法后面加 throws
关键字使得整个应用程序对异常开放;而 .Net
则可以通过给应用程序域(Application Domain)的 UnhandledException
事件添加委托达到捕捉所有异常的目的,很显然这又是对立互补的。
因此,就好像一个是“正反”,一个是“反正”,加在一起“正反反正”都是一样的,对于达到控制异常的目录来说,是没有区别的。
很多
Java 爱好者都鄙视 .Net
的这种行为,一方面他令程序变得不够健壮,因为默认情况下没有强制的办法要求所有的异常都被处理,或被正确处理;另外,他为调试增加了困难,不借助文档或代码你将无法了解到一个方法可能抛出什么异常,而当一个异常被抛出的时候,同时异常处理代码又写得不够完善,你将不得不仔细查看整个调用栈来确定异常出现的位置,而对于这一点
Java 默认是强制的。
但是
Anders 的想法总是有道理的。
- .Net
代码写起来非常容易。这是对于初学者,或者那些只是想实现一些测试性小功能的人而言,你完全没有必要考虑太多异常处理的细节,你要的就是写代码,然后让他跑起来。这样的简单性无疑是你希望看到的,这样的简单性无疑更有利于
.Net
在市场上的推广。由于他在这方面并没有什么理论上的漏洞,也就仍然适合构建庞大的项目,只是感觉没有那么舒服罢了。
-
一定程度上增加了程序的安全性。难道不捕捉异常可以被成为是安全的吗?这个话也许要从另外一方面来想,前面说过,有些
Java
程序员(绝对不占少数)为了图省事,在强行捕捉异常的压迫下,选择捕捉异常的基类型,也就是捕捉所有的异常。这样当有你无法处理的异常出现时,他们就溺死在了你的代码中,而外面的程序全然不知,还在以一种不确定的状态运行着,这就可能是危险的开始。而如果是
.Net,那么 Unhandled Exception
会被虚拟机捕获,导致程序异常退出,虽然这从面子上对于用户不是一个好的交代,但是深层次地他避免了程序在危险的状态下继续运行。
总之,萝卜白菜各有所爱。我的这篇帖子力求公正地讨论了这个问题,希望能对你有所帮助
分享到:
相关推荐
linux系统下部署TOMCAT异常错误java.net.UnknownHostException :bogon: bogon 主要原因是主机映射原因 修改hosts文件即可
java.net.SocketException: Unrecognized Windows Sockets error: 0: no Inet4Address associated with interface 本文提供了在Win7或Vista系统下解决这个异常信息的办法。
NULL 博文链接:https://zhoudan241.iteye.com/blog/1432014
最近纠结致死的一个java报错java.net.SocketException: Connection reset 终于得到解决
下面小编就为大家带来一篇java.net.MalformedURLException异常的解决方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
主要介绍了java.net.ConnectException: Connection refused问题解决办法的相关资料,需要的朋友可以参考下
解决问题关于tomcat的端口异常错误信息
Java基础入门教程 第7章 Java中的异常处理(共26页).ppt Java基础入门教程 第8章 文件流的输入输出操作(共37页).ppt Java基础入门教程 第9章 Java的高级特性(共32页).ppt jdk api 1.7.chm JDK_API_1_6_zh_...
读取异常修复异常中抱怨的事情再试一次意识到通过“修复” URL 以便 Java 将根据 rfc3986 (java.net.URI) 接受它,您正在更改字节。 它与原始版本不完全相同。 大多数情况下,这不会导致任何可测量的差异,但有您的...
word源码java 教程 您好,欢迎来到 . 在这里您可以找到网站上发布的示例的源代码。 请注意:Java 是一种伟大而庞大的编程语言,您...javatutorial.net 的链接,我会很高兴,这样其他人也可以从免费知识中受益。 谢谢!
帮助大家复习java基础知识其中有 hashCode 2 toString 2 finalize 2 用已学知识做出简单的房屋出租系统 3 类方法使用注意事项和细节讨论 4 main()方法 4 代码块 4 代码块使用注意事项和细节 5 单例模式 6 final...
第1个异常是 java.net.BindException:Address already in use: JVM_Bind。 该异常发生在服务器端进行new ServerSocket(port)(port是一个0,65536的整型值)操作时。异常的原因是以为与port一样的一个端口已经...
体验 .net2.0 的优雅(2) -- ASP.net 主题和皮肤 NET2.0系列介绍(一).NET 2.0 中Web 应用程序主题的切换 ASP.NET 2.0 中Web 应用程序主题的切换 2.0正式版中callback的一些变化+使用示例(ASP.NET 2.0) Server ...
Spring.NET以Java版的Spring框架为基础,将Spring.Java的核心概念与思想移植到了.NET平台上。 第一章 序言 第二章 简介 2.1.概述 2.2.背景 2.3.模块 2.4.许可证信息 2.5.支持 第三章 背景 3.1.控制反转 第...
完整版 Java基础入门教程 Java程序语言设计 06 异常处理 异常和垃圾收集(共27页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络编程 JDBC(共21页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 ...
JAVA_6 异常处理Exceptions JAVA_7 IO输入输出 JAVA_8 AWT图形界面编程 JFC AWT Swing JAVA_8 AWT图形界面编程 JFC Swing JAVA_9 Applet JAVA_10 线程 JAVA_11 网络程序设计 JAVA_12 JFC Swing JAVA_13 JDBC JAVA_13...
Java异常分装实例,实例详解请访问博主博客:http://blog.csdn.net/u013142781
java 加载dll 异常,包含调试运行和打jar 可以参考https://blog.csdn.net/ADdhtfdhdg/article/details/108754087
上海交通大学 Java语言程序设计 JAVA讲义 第08章 java异常处理机制(共45页).ppt 上海交通大学 Java语言程序设计 JAVA讲义 第09章 Java输入输出及文件操作(共82页).ppt 上海交通大学 Java语言程序设计 JAVA讲义 ...
Java SE编程入门教程 java异常(共57页).pptx Java SE编程入门教程 java正则(共8页).pptx Java SE编程入门教程 properties(共3页).pptx Java SE编程入门教程 String字符串(共27页).pptx Java 位运算.docx ...