今天在看hadoop源码时,想想自己最近在做的那个系统,发现很多异常处理的方式不对,还是按照传统的异常处理方式(即:采用返回值来标识程序出现的异常情况)。而hadoop中很多方法的声明是有异常抛出的,而我的系统中的很多方法的声明都没有抛出异常。只是判断了异常情况,并输出了错误提示,但是并没有抛出异常。

org.apache.hadoop.hdfs.protocol包下的Block类的readFields()方法:

public void readFields(DataInput in) throws IOException {this.blockId = in.readLong();this.numBytes = in.readLong();this.generationStamp = in.readLong();if (numBytes < 0) {throw new IOException("Unexpected block size: " + numBytes);//抛出异常,要是的话就不会抛出,而只是System.out.println错误提示,}

1.如果方法声明名里面有throws异常,那么方法体里面可以不抛出异常。因为可以在方法声明中包含异常说明,但实际上却不抛出!这样做的好处是,为异常先占个位置,以后就可以抛出这种异常而不用修改修改已有的代码。在定义抽象基类和接口时这种能力很重要,这样派生类或接口实现类就能够抛出这些预先声明的异常。

2.为什么有的方法声明里面没有throws,但方法体里面却抛出了异常?从RuntimeException继承的异常,可以在没有异常说明throws的情况下被抛出!对于Runtime异常(也称为非检查的异常unchecked exception),编译器不需要异常说明。只能在代码中忽略RuntimeException(及其子类)类型的异常,其他类型的异常的处理都是由编译器强制实施的。究其原因,RuntimeException代表的是编程错误。

3.运行时异常会被Java虚拟机自动抛出!

《有效处理Java异常三原则》http://www.importnew.com/1701.html

1. 异常处理基础

1.1 System.out.println是高代价的。调用System.out.println会降低系统吞吐量。

1.2 在生产环境中别用异常的printStackTrace()方法。printStackTrace默认会把调用的堆栈打印到控制台上,在生产环境中访问控制台是不现实的。

2. 异常处理基本原则

2.1 如果你不能处理异常,不要捕获该异常。

2.2 如果要捕获,应在离异常源近的地方捕获它。

2.3 不要吞没你捕获的异常。

*(就是捕获的异常,但是什么也不做)

2.4 除非你要重新抛出异常,否则把它log起来。

2.5 当一个异常被重新包装,然后重新抛出的时候,不要打印statck trace。

2.6 用自定义的异常类,不要每次需要抛出异常的时候都抛出java.lang.Exception。方法的调用者可以通过throws知道有哪些异常需要处理--所以它是自我描述的。

2.7 如果你编写业务逻辑,对于终端用户无法修复的错误,系统应该抛出非检查的异常(unchecked exception);如果你编写一个第三方的包给其他的开发人员用,对于不可修复的错误要用需要检查的异常(checked exception)。

2.8 绝对不要因为写throws语句会让你用起来不舒服,而不声明需要检查的异常。

2.9 应用级别的错误或不可修复的系统异常用非检查的异常(unchecked exception)抛出。

*(注意是错误,意味着不可修复,比如配置文件错误)

2.10 根据异常的粒度组织你的方法

其他参考文章:

http://klyuan.iteye.com/blog/72170

http://blog.csdn.net/luqin1988/article/details/7970792

http://www.onjava.com/pub/a/onjava/2003/11/19/exceptions.html  对应的译文,不怎么准确:http://blog.sciencenet.cn/blog-252888-761119.html

http://www.oschina.net/question/92866_15634

http://www.importnew.com/1701.html

http://sunflowers.iteye.com/blog/767175

1、 异常分类
a. RuntimeException 及其子类不要求捕捉,而其它的异常要求捕捉随便举几个 RuntimeException 子异常,有:数组越界异常、空指针异常、0作除数异常

b. 非RuntimeException 异常有:Socket异常、IO异常等

c. 对比一下我们就会发现,RuntimeException 是在程序中可以完全避免的, 
c1. 比如数组越界异常,只要我在程序里作个判断,如果要访问的数组元素下标和数组的长度作一下比较就知道会不会越界, 
c2. 再比如空指针异常,如果在访问对象时判断一下对象的变量是否为空就可以了。 
c3. 而非RuntimeException 则是程序无法避免的,比如IO异常,你的程序正在读一个文件,而这个文件所在磁盘出现了坏道,这就必然会引发IOException,这是不是靠编程高手编写完美的程序就可以法避免得了的,程序所能做的只有出现异常之后怎么处理的问题

2、 异常处理原则之一:延迟捕获
意思是,当异常发生时,不应立即捕获,而是应该考虑当前作用域是否有有能力处理这一异常的能力,如果没有,则应将该异常继续向上抛出,交由更上层的作用域来处理。

一个例子:某方法String readFile(String filename),会去尝试读出指定文件的内容并返回,其使用FileInputStream来读取指定文件,而FileInputStream的构造方法会抛出FileNotFoundException,这是一个Checked Exception。那么readFile方法是应该捕获这个异常,还是抛出这个异常呢?很显然应该抛出。因为readFile这个方法可能会在不同的场景下,被不同的代码调用,在这些场景中,出现“文件未找到”的情况时的处理逻辑可能是不同的,例如某场景下要发出告警信息,另一场景下可能会尝试从另一个文件中读取,第三个场景下可能需要将错误信息提示给用户。在这种情况下,在readFile方法内的作用域中,是处理不了这个异常的,需要抛出,交由上层的,具备了处理这个异常的能力的作用域来处理

在服务器端和dao段 都是抛出异常很少有捕获 捕获在客户端 因为不能吧异常抛给用户。从dao到服务器到客户端都是层层抛出 到客户端必须捕获处理 可能给用户提示信息和给程序猿一些记录 方便交互和处理

3、 个人经验
a. 以MVC框架为例,首先controller层必须捕获异常,一般情况下不允许将系统内部的异常不做任何封装处理直接抛给客户端,这样对系统来说会暴露过多信息(异常栈信息都抛给客户端,可能会把SQL结构都抛出去),这是不安全因素;同时,这对用户来说也是不友好的,让一些不搞计算机的同学看得一头雾水,并且怀疑网站的正规性与可靠性,可能会直接影响未来的业务。因此,通常需要在controller层封装一些错误码、用户友好语句(系统维护中等等欺骗用户的语句)。当然这也不是铁律,有的时候需要后台进行较检,可能需要抛出一些非公用的异常信息到界面上,比如之前车贷项目中用到过的上传附件检查,就是用后台异常提示用户的。还有就是传入参数有效性较检,也需要抛出自定义异常(用@NotNull或NotEmpty等注解抛出message信息),即不需要捕获后统一处理返回到用户界面

b. 接着说一下service层,业务层需要处理业务逻辑,当然这一层不需要考虑参数是否为空,需要考虑的仅仅是从dao查询相关的异常,比如ConnectionExcepion、SQLException、BadSQLGrammerException等异常,这些异常我通常会去捕获,因为这些异常涉及到业务逻辑是否能正常执行,确实是service该考虑的事。做法是try…catch…捕获所有Exception,然后在catch中用logger.error(“message, e = {}”, e.getMessage())记录日志信息,用于到时候定位error代码位置,然后根据实际业务情况,看这个异常捕获后是否需要用一个异常封装一下信息抛给控制层,然后由控制层统一处理也好或者直接返回给用户)。注意,业务层异常不是用于捕获NullPointerException等无聊的代码健壮性问题,这些都是业务层代码逻辑没控制好,查询值需要做一下非空判断

c. 至于dao层,我想没必要说了吧,一般我也不写实现类,持久层的mybatis3.X都用动态代理来实现了。 BTW,try…catch最好有针对性,不要把所有美容都放到try里面检查是否有异常,一般来说总有些无关异常的语句可以提到异常块之外,反正能提就提。

4、 异常总结
异常:

1、 自定义异常 
2、 重写方法需要抛出与原方法所抛出异常类型一致异常或不抛出异常 
3、 异常类型图: 
Throwable -> Error(虚拟机错误) 
Exception -> RuntimeException(可以抛出也可以不抛出) 
4、 先捕获小的,再捕获大的

public class Test {
    public void regist(int num) throws MyException {
        if (num < 0) 
            throw new MyException("人数为负值,不合理", 10000);
        System.out.println("登记人数:" + num);
    }

public void manager() {
        try {
            regist(-10);
        } catch(MyException e) {
            System.out.println("登记失败,出错类型码: " + e.getId());
            e.printStackTrace();
        }
        System.out.println("操作结束");
    }
    public static void main(String[] args) {
        Test t = new Test();
        t.manager();
    }

}

class MyException extends Exception {
    private int id; // 异常码
    public MyException(String message, int id) {
        super(message);
        this.id = id;
    }

public int getId() {
        return this.id;
    }
}
---------------------

java 捕获异常还是抛出异常相关推荐

  1. java捕获异常和抛出异常_Java捕获多个异常,重新抛出异常

    java捕获异常和抛出异常 In Java 7, catch block has been improved to handle multiple exceptions in a single cat ...

  2. [转载] java 捕获异常还是抛出异常

    参考链接: 捕获基类和派生类为异常 今天在看hadoop源码时,想想自己最近在做的那个系统,发现很多异常处理的方式不对,还是按照传统的异常处理方式(即:采用返回值来标识程序出现的异常情况).而hado ...

  3. java异常——捕获异常+再次抛出异常与异常链

    java异常--捕获异常+再次抛出异常与异常链 参考文章: (1)java异常--捕获异常+再次抛出异常与异常链 (2)https://www.cnblogs.com/jpfss/p/9454592. ...

  4. java学习中,异常和错误的简介、捕获异常、抛出异常、自定义异常、finally关键字(java 学习中的小记录)

    java学习中,异常和错误的简介.捕获异常.抛出异常.自定义异常.finally关键字(java 学习中的小记录) 参考文章: (1)java学习中,异常和错误的简介.捕获异常.抛出异常.自定义异常. ...

  5. java catch抛出异常_java异常——捕获异常+再次抛出异常与异常链

    [0]README 0.1) 本文描述+源代码均 转自 core java volume 1, 旨在理解 java异常--捕获异常+再次抛出异常与异常链 的相关知识: [1]捕获异常相关 1.1)如果 ...

  6. java将异常写到text,java捕获异常信息存入txt文件示例

    捕获程序中出现的异常 可用于后期维护的必要性!做简单的测试 !package helpEntity; import java.io.BufferedReader; import java.io.Fil ...

  7. java中用来抛出异常的关键是_java中用来抛出异常的关键字是 catch

    java中用来抛出异常的关键字是 catch 答:× 马克思主义的来源包括() 答:马克思主义的政治经济学 科学社会主义 马克思主义哲学 "风口理论"又叫"飞猪理论&qu ...

  8. java 同步块 抛出异常_java问题合集(一)

    垃圾回收算法 引用计数法,标记清除法,标记压缩清除法(Java中老年代采用),复制算法(Java中新生代采用),分代法(Java堆采用),分区算法. 重要的三句话: 垃圾回收器只知道释放那些经由new ...

  9. java如何快速抛出异常,异常 - 如何抛出异常 - 《Java 编程要点(Essential Java)》 - 书栈网 · BookStack...

    如何抛出异常 在你可以捕获异常之前,一些代码必须抛出一个异常.任何代码都可能会抛出异常:您的代码,来自其他人编写的包(例如Java平台附带的包)或Java运行时环境的代码.无论是什么引发的异常,它总是 ...

最新文章

  1. Python数据挖掘:绘制直方图,设置上下限和步长,绘制子图
  2. log4net报错集
  3. tf.app.flags和tf.app.run的使用
  4. matlab畸变校正代码_关于OpenCV中的去畸变
  5. c语言中通过指针引用数组,C语言基础(二)
  6. Maven实战. 3.7NetBeans Maven插件简单使用
  7. 去雾综述_图像去雾的算法历史与综述
  8. micropython中文教程.pdf_micropython中文教程
  9. 摩托罗拉MT788刷机
  10. 在线CSV转XML工具
  11. cf C. Inna and Candy Boxes
  12. ERROR 1045 (28000): Access denied for user 'root'@'localhost' 的解决方法
  13. Java代码页面显示报表_Web报表开发中使用快逸报表分页标签:显示第几页和共几页...
  14. delphi 热部署_DelphiWebMVC微信公众号开发
  15. Understand(代码分析工具)的安装与使用教程
  16. 完美解决“word无法创建工作文件,请检查临时环境变量”
  17. Java中get和set的作用、用法
  18. oracle12c安全补丁包,Oracle 12c 及以上版本补丁更新说明及下载方法
  19. 蜻蜓飞过,从此智能硬件厂商有了儿童梦工厂
  20. 微信小程序用户信息解

热门文章

  1. 前端电商项目实战,如何从 0 开始创造一个【考拉海购官网】?( 共6节教程 )
  2. MySQL——触发器的创建和使用总结
  3. Chrome 自动化交互利器:用 tampermonkey 向页面注入自定义 Javascript
  4. 公钥私钥 多久过期_公钥和私钥的解释
  5. java多线程交替打印_使用Java实现三个线程交替打印0-74
  6. Java 设计模式最佳实践:一、从面向对象到函数式编程
  7. HCFT和HCFTstar在OTB数据集中测试的接口函数
  8. R技术、函数知识点总结
  9. 记录下诺瓦科技笔试(软开)
  10. 步进电机梯形曲线加减速运动算法实现