Java里面的java异常处理有什么作用?仅仅是发现错误吗?

Java为什么将异常分为受检的和运行时异常?这样分的依据和好处是什么?
比如用到FileInputStream时必须捕获FileNotFoundException,也就是受检类型的异常,但找不到文件这种异常应该是运行时才能发现的。
按投票排序
我理解,受检的异常在编译的时候就会检查,是你对使用你这个method函数的一个定义,就是对引用这个函数的说,你引用这个函数,我会告诉你,我这里处理不了这个异常,可能你会有更多的信息,可以针对当时的业务逻辑来处理这个异常,或者你也不知道怎么处理,那你就继续往上抛,比如你说的FileNotFoundException,FileInputStream不知道怎么处理,但你用FileInputStream,你可以决定找不到文件有没有影响我的业务逻辑,我是能继续呢,还是继续往上抛出运行异常就是程序错误,无法在继续下去,最多的就是NullPointerException,对象已经是空的了,程序还怎么往下跑
所有的运行时异常都是可以在发生之前检测到并且避免的,这意味着一段代码如果写得好,将不会有抛出运行时异常的可能。因此,运行时异常被抛出时,程序员应该检查代码中的bug,而不是catch它。
已有帐号?
无法登录?
社交帐号登录完美解析Java异常,六种异常处理的陋习
六种Java异常处理的陋习
  你觉得自己是一个Java专家吗?是否肯定自己已经全面掌握了Java的异常处理机制?在下面这段代码中,你能够迅速找出异常处理的六个问题吗?
  1 OutputStreamWriter out = ...
  2 java.sql.Connection conn = ...
  3 try { // ⑸
  4  Statement stat = conn.createStatement();
  5  ResultSet rs = stat.executeQuery(
  6    &select uid, name from user &);
  7  while (rs.next())
  9   out.println( &ID: & + rs.getString( &uid &) // ⑹
  10     &,姓名: & + rs.getString( &name &));
  11  }
  12  conn.close(); // ⑶
  13  out.close();
  15 catch(x) // ⑵
  17  ex.printStackTrace(); //⑴,⑷
  作为一个Java程序员,你至少应该能够找出两个问题。但是,如果你不能找出全部六个问题,请继续阅读本文。
  本文讨论的不是Java异常处理的一般性原则,因为这些原则已经被大多数人熟知。我们要做的是分析各种可称为&反例&(anti-pattern)的违背优秀编码规范的常见坏习惯,帮助读者熟悉这些典型的反面例子,从而能够在实际工作中敏锐地察觉和避免这些问题。
  反例之一:丢弃异常
  代码:15行-18行。
  这段代码捕获了异常却不作任何处理,可以算得上Java编程中的杀手。从问题出现的频繁程度和祸害程度来看,它也许可以和C/C++程序的一个恶名远播的问题相提并论??不检查缓冲区是否已满。如果你看到了这种丢弃(而不是抛出)异常的情况,可以百分之九十九地肯定代码存在问题(在极少数情况下,这段代码有存在的理由,但最好加上完整的注释,以免引起别人误解)。
  这段代码的错误在于,异常(几乎)总是意味着某些事情不对劲了,或者说至少发生了某些不寻常的事情,我们不应该对程序发出的求救信号保持沉默和无动于衷。调用一下printStackTrace算不上&处理异常&。不错,调用printStackTrace对调试程序有帮助,但程序调试阶段结束之后,printStackTrace就不应再在异常处理模块中担负主要责任了。
  丢弃异常的情形非常普遍。打开JDK的ThreadDeath类的文档,可以看到下面这段说明:&特别地,虽然出现ThreadDeath是一种&正常的情形&,但ThreadDeath类是Error而不是Exception的子类,因为许多应用会捕获所有的Exception然后丢弃它不再理睬。&这段话的意思是,虽然ThreadDeath代表的是一种普通的问题,但鉴于许多应用会试图捕获所有异常然后不予以适当的处理,所以JDK把ThreadDeath定义成了Error的子类,因为Error类代表的是一般的应用不应该去捕获的严重问题。可见,丢弃异常这一坏习惯是如此常见,它甚至已经影响到了Java本身的设计。
  那么,应该怎样改正呢?主要有四个选择:
  1、处理异常。针对该异常采取一些行动,例如修正问题、提醒某个人或进行其他一些处理,要根据具体的情形确定应该采取的动作。再次说明,调用printStackTrace算不上已经&处理好了异常&。
  2、重新抛出异常。处理异常的代码在分析异常之后,认为自己不能处理它,重新抛出异常也不失为一种选择。
  3、把该异常转换成另一种异常。大多数情况下,这是指把一个低级的异常转换成应用级的异常(其含义更容易被用户了解的异常)。
  4、不要。
  结论一:既然捕获了异常,就要对它进行适当的处理。不要捕获异常之后又把它丢弃,不予理睬。
  反例之二:不指定具体的异常
  代码:15行。
  许多时候人们会被这样一种&美妙的&想法吸引:用一个catch语句捕获所有的异常。最常见的情形就是使用catch(Exception ex)语句。但实际上,在绝大多数情况下,这种做法不值得提倡。为什么呢?
  要理解其原因,我们必须回顾一下catch语句的用途。catch语句表示我们预期会出现某种异常,而且希望能够处理该异常。异常类的作用就是告诉Java编译器我们想要处理的是哪一种异常。由于绝大多数异常都直接或间接从java.lang.Exception派生,catch(Exception ex)就相当于说我们想要处理几乎所有的异常。
  再来看看前面的代码例子。我们真正想要捕获的异常是什么呢?最明显的一个是,这是JDBC操作中常见的异常。另一个可能的异常是IOException,因为它要操作OutputStreamWriter。显然,在同一个catch块中处理这两种截然不同的异常是不合适的。如果用两个catch块分别捕获和IOException就要好多了。这就是说,catch语句应当尽量指定具体的异常类型,而不应该指定涵盖范围太广的Exception类。
  另一方面,除了这两个特定的异常,还有其他许多异常也可能出现。例如,如果由于某种原因,executeQuery返回了null,该怎么办?答案是让它们继续抛出,即不必捕获也不必处理。实际上,我们不能也不应该去捕获可能出现的所有异常,程序的其他地方还有捕获异常的机会??直至最后由JVM处理。
如异常没有得到解决,请继续查看以下解决方法:
暂无相关解决方法。
热点异常解决方法
最新异常解决方法
随机异常解决方法什么情况下使用异常处理?
对于异常处理总是抓不住重点,到底什么时候使用异常处理呢?&br&&br&比如&br&很多文章里举除数为0的例子,难道不是先判断除数,再进行除法吗,为什么需要异常处理?&br&还有FileNotFoundException,难道不是先判断文件是否存在,然后再进行文件访问吗?&br&&br&我能想到的就是,多进程系统上,因为判断和处理过程不是原子操作,所以在它们之间,量、状态、环境有可能会被改变,所以需要捕获异常,进行异常处理。&br&&br&是上述这样的原因吗,&b&使用异常处理的根本是多进程和非原子操作?&/b&&br&看教程和文章实在想不到根本,还望指教。&br&&br&&a href=&///?target=http%3A//en.wikipedia.org/wiki/Exception_handling& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Exception handling - 维基&i class=&icon-external&&&/i&&/a&&br&--------------------------------------------------------------------------------------------------------------&br&谢谢回答,现在令我疑惑的不仅仅是问题本身了,为什么20个答案却包含着好几种观点?&br&&br&总结几种观点:&br&1、异常处理可以替代c时代的errno这样的错误处理方式,而且作用域并非全局,可以顺着方法的调用一直向上,直到被捕获处理,是一种语法糖样的东西,而且有一种面向对象的样子。&br&2、因为底层API要抛异常,不try/catch程序就挂掉。(这不算回答本问题,但开发中往往就是这样。当然仅try/catch不能囊括异常处理,还应该有throw等概念)&br&3、上述所说的多线程和非原子操作。(但现在意识到貌似这并非根本原因,甚至原因都算不上)&br&4、异常处理主要目地是为了强制方法调用者处理可能发生的错误。(应该用断言,这种看法自认为是错误的)&br&5、不要用异常处理,应该使用状态返回值。(额)&br&6、如果使用if/else,要很多的判断,但是try/catch很简单。&br&&br&相关问题:&br&&a href=&/question/& class=&internal&&对使用 C++ 异常处理应具有怎样的态度? - 编程&/a&&br&&a href=&/question/& class=&internal&&Swift 为什么没有异常处理? - 编程语言&/a&
对于异常处理总是抓不住重点,到底什么时候使用异常处理呢?比如很多文章里举除数为0的例子,难道不是先判断除数,再进行除法吗,为什么需要异常处理?还有FileNotFoundException,难道不是先判断文件是否存在,然后再进行文件访问吗?我能想到的就是,多进程系统上,因为判断和处理过程不是原子操作,所以在它们之间,量、状态、环境有可能会被改变,所以需要捕获异常,进行异常处理。是上述这样的原因吗,使用异常处理的根本是多进程和非原子操作?看教程和文章实在想不到根本,还望指教。--------------------------------------------------------------------------------------------------------------谢谢回答,现在令我疑惑的不仅仅是问题本身了,为什么20个答案却包含着好几种观点?总结几种观点:1、异常处理可以替代c时代的errno这样的错误处理方式,而且作用域并非全局,可以顺着方法的调用一直向上,直到被捕获处理,是一种语法糖样的东西,而且有一种面向对象的样子。2、因为底层API要抛异常,不try/catch程序就挂掉。(这不算回答本问题,但开发中往往就是这样。当然仅try/catch不能囊括异常处理,还应该有throw等概念)3、上述所说的多线程和非原子操作。(但现在意识到貌似这并非根本原因,甚至原因都算不上)…
按投票排序
简单说就是,函数无法满足调用方的期望的时候使用异常。放在现实场景中就是,当上级交待给你的任务无法完成的时候,使用异常。异常的目的是将这个问题传递给调用方解决。就像在现实环境中,搞不定的时候找老板一样。
通常情况下,使用者(包括用户、代码库的使用者)所引发的错误,需要通过异常机制来处理。因为异常发生的时候,原订的执行流程就无法继续,但对于用户来讲,他们不能因为这样的错误就终止程序的使用,所以提供给程序设计者异常机制,让设计者决定发生意外的时候应该做些什么。而这种意外的产生原因是用户,用户的操作千千万万,导致的结果也可能千奇百怪,但是他们的操作若使得原有流程无法继续,那么就是异常。楼主说的判断文件先存在,再读写文件,其实就是这个问题,按照程序的流程,可以保证在判断是否存在的时候,文件的存在性,但是不能保证在真正操作文件的时候文件的存在性(例如判断的时候文件还在,真正操作之前却被用户自己删掉了)。因为流程上无法对流程外的用户行为(用户删文件)作出保证,所以需要异常机制。我认为,用户在程序运行时触发所导致的错误,需要异常机制来捕捉和处理。程序设计中还有一种叫断言(ASSERT)的东西,这种机制是用来约束程序设计者的,例如某些库的某些函数,在文档中约定了,这个函数的参数必须是&0,那么你在编程的时候愣是硬生生输入一个0,那么这时候就应该选择断言,用于帮助程序设计者及早的发现自己程序中的错误(这种错误是设计上的错误所引发的,而非用户的操作所导致的),而不是用异常机制去处理。所以,由程序员设计不足所导致的错误,需要用断言来捕捉和处理。
我觉得相对于事先判断异常并处理大概主要有 3 个方面的优点:1、增强代码的鲁棒性而不必影响程序的主逻辑,使程序员专注于程序的主逻辑,保持代码的简洁清晰;2、一些低调用级别的代码块没有判断和处理其上级调用模块的权限或者根本无法判断,只能由其上级调用模块来决定下一步怎么做,这时当前模块可以不用处理,将错误抛出给调用者;3、对于异常的判断是就地实时的,也就是与代码运行是实时的,而事先判断精确来讲其实是提前的,这样就不一定能准确地发现异常。
你给的链接里也提到了,对于C++, Java, Python和Ruby来说,Exception的一大作用就是用来改变程序的control flow。比如说你自己写的a()调用b(), b()调用c()....y()调用z(),z()throw一个FileNotFoundException就可以直接从这么多层的stack里return回来。否则,你就要让a...z都要对每一次调用检查是否返回了错误代码。
是啊,你先判断除数,再进行触发,那么你在if (a == 0)这个分支里准备写什么?// 看了评论发现初学者真是好多好多……
当前函数无法将某种状态传递到外面的时候就要用异常处理。如果你用返回值或者某个参数作为函数成功与否的标志,就没有必要用了。
你写了一个底层函数,出了错误,要return,这时候要定义好return的错误类型,return error(0) if 0return error(1) if 1return error(2) if 2return error(3) if 3return error(4) if 4return error(5) if 5那么在上一级调用的时候,又要根据值来判断返回什么,又要定义一堆if。每调用一层就要定义一堆error信息这样不累吗,出错了直接抛个异常出去,不要管上面哪一层来捕获处理,反正我就是抛了。我抛的是个具体的异常。至于顶上程序怎么把这些异常分类处理,我就不管了。谁调用谁处理,不处理就崩溃了
楼主混淆了设计和调用。设计一个除法必须考虑熊孩子把除数误设为0的情况,调用者在调用前自然得保证除数不为0。所以前者需要一个异常后者不需要。
如果你能保证你的所有数据都有 transactionally roll back 能力,就可以。实际上,除非你的所有的数据都是简单的纯内存数据和 relational DB,是不可能的。所以不要用异常。
异常处理主要目地是为了强制方法调用者处理可能发生的错误(已检查异常)。你说的判断是否为0,如果方法调用者忘了判断返回值咋办?已检查异常就是干这个的!
已有帐号?
无法登录?
社交帐号登录

我要回帖

更多关于 java异常处理 的文章

 

随机推荐