1、什么是异常

结构不佳的代码不能运行,这是Java的基本理念。

发现错误的理想时机是在编译期。然而,编译器并不能发现所有的错误,余下的问题就需要在程序运行时解决。这就需要错误能通过某种方式,把适当的信息传递给特定的接收者处理。Java中的异常处理的目的在于通过使用少量的代码来简化大型、可靠的程序的生成,通过此方式让你的应用中没有未处理的错误,而且它还带来了一个明显的好处:降低错误处理代码的复杂度。

异常,根据字面理解,有意外之意。把它置于代码层面来理解,即阻止了当前方法或作用域继续执行。

在Java中,异常被当做对象来处理,其基类是Throwable。

2、Java中的异常类型

Java从Throwable直接派生出Exception和Error。其中Exception是可以抛出的基本类型,在Java类库、方法以及运行时故障中都可能抛出Exception型异常;Error表示编译时和系统错误。异常类的结构层次图如下:

典型的RuntimeException包括NullPointerException, IndexOutOfBoundsException, IllegalArgumentException等;非RuntimeException包括IOException, ClassNotFoundException等。

而按照编译器检查方式划分,异常又可以分为检查型异常(CheckedException)和非检查型异常(UncheckedException)。Error和RuntimeException合起来称为UncheckedException,之所以这么称呼,是因为编译器不检查方法是否处理或者抛出这两种类型的异常,因此编译期间出现这种类型的异常也不会报错,默认由虚拟机提供处理方式。除了Error和RuntimeException这两种类型的异常外,其它的异常都称为Checked异常。

3、Java如何处理异常

3.1 try-catch, try-finally, try-catch-finally

对于checked类型异常,我们要么对它进行处理,要么在方法头使用throws抛出。

public static void createFile() throws IOException{
    File file = new File("C:/test.txt");
    if(!file.exists()){
            file.createNewFile();
    }
}
public static void main(String[] args) {
    try {
        createFile();
    } catch (IOException ex) {
        // handle exception here
    }
}

关于catch需要注意的几点:

1)、参数的异常类型必须是Throwable类或者其子类。

2)、从上往下的catch语句,其参数类型必须按照从子类到父类顺序,因为一旦匹配到一个类型,就会忽略往后的catch。比如IOException必须放到Exception前面,否则编译器会报错。

3)、可以有一个或者多个catch语句,甚至如果有finally语句的情况下,可以没有catch语句,如try-finally。

想要捕获多个异常,可以使用多个catch语句,JDK7以后提供了另外一种方式:多重捕获(multi-catch)。

try{
    // other code
} catch (IOException | SQLException ex) {
    throw ex;
}  

4)、不要忽略异常。空的catch块会使异常达不到应有的目的,除非诸如关闭FileInputStream的时候,因为你还没有改变文件的状态,因此不必执行任何恢复动作,并且已经从文件中读取到所需要的信息,因此不用终止正在进行的操作。

关于finally需要注意的几点:

1)、finally中的代码总是会被执行,除非在执行try或者catch语句时虚拟机退出(System.exit(1))。

2)、finally块可以做一些资源清理工作,如关闭文件、关闭游标等操作。

3)、finally块不是必须的。

另外,如果在try和finally块中都执行了return语句,最终返回的将是finally中的return值。

3.2 异常链

常常想要在捕获一个异常后抛出另外一个异常,并且希望把原始异常信息保存下来,这就是异常链。在JDK1.4以后,Throwable子类在构造器中可以接受一个cause对象作为参数,表示原始异常,通过这样把原始异常传递给新的异常,使得即使在当前位置创建并抛出了新的异常,也能通过这个异常链追踪到异常最初发生的位置。

但在Throwable子类中,只有Error, Exception, RuntimeException三类异常类提供了带cause参数的构造器,其它类型的异常则需要通过initCause()方法。例如定义了CustomException类,可以这样使用:

CustomException cmex = new CustomException();
cmex.initCause(new NullPointerException);
throw cmex;

这样一来,CustomException继承自Exception或RuntimeException,就属于自定义异常了。

一般来说,自定义异常的作用有以下情形:

1)、将检查型异常转换为非检查型异常。

2)、在产生异常时封装上下文信息、定义异常码、收集环境对象,有利于信息的传递。

4、异常使用指南

1)、在知道该如何处理的情况下才捕获异常。

2)、自定义异常类型,用以封装所有的检查型异常。

3)、在程序的边界进行异常捕获。如服务端相应客户端的请求,在出口处catch内部有可能产生的异常,并统一throw一个封装过的异常给客户端,免得暴露服务端敏感信息。

4)、只针对异常的情况才使用异常。不要在所有的代码中习惯性地使用try-catch,因为这会影响性能。

5)、抛出与抽象相对的异常。如果方法抛出的异常与它执行的任务没有明显的联系,这种情形会使人不知所措。为了避免这个问题,更高层的实现应该捕获低层的异常,同时抛出可以按照高层抽象进行解释的异常,这种做法被称为异常转译(exception translation),如下:

try{
    // use lower-level abstraction to do our bidding
} catch(LowerLevelException ex){
    throw new HigherLevelException(...);
}

另外一种特殊的异常转译称为异常链,上面已作描述。如果低层的异常对于调试导致高层异常的问题非常有帮助,使用异常链就很合适。高层的异常提供访问方法(Throwable.getCause)来获得低层的异常。

6)、每个方法抛出的异常要有文档描述。利用Javadoc的@throws标记,记录抛出每个异常的条件。如果一个方法可能抛出多个异常,不要使用这些异常类的某个超类。如不要声明一个方法“throws Exception”或“throws Throwable”,这将没有任何指导信息。

参考:

Java的Exception和Error面试题10问10答

去除Java的受检异常?

有关JAVA异常和错误(ERROR)的处理

Java异常处理和设计

浅析Java异常的更多相关文章

  1. 浅析java内存管理机制

    内存管理是计算机编程中的一个重要问题,一般来说,内存管理主要包括内存分配和内存回收两个部分.不同的编程语言有不同的内存管理机制,本文在对比C++和Java语言内存管理机制的不同的基础上,浅析java中 ...

  2. 浅谈java异常[Exception]

    学习Java的同学注意了!!! 学习过程中遇到什么问题或者想获取学习资源的话,欢迎加入Java学习交流群,群号码:589809992 我们一起学Java! 一. 异常的定义 在<java编程思想 ...

  3. 基础知识《十》java 异常捕捉 ( try catch finally ) 你真的掌握了吗?

    本文转载自  java 异常捕捉 ( try catch finally ) 你真的掌握了吗? 前言:java 中的异常处理机制你真的理解了吗?掌握了吗?catch 体里遇到 return 是怎么处理 ...

  4. Java异常体系及分类

    上图是基本的java异常体系结构. 主要分为2大类:Error和Exception 1.Error:描述了Java运行系统中的内部错误以及资源耗尽的情形.应用程序不应该抛出这种类型的对象,一般是由虚拟 ...

  5. Java异常之自定义异常

    哎呀,妈呀,又出异常了!俗话说:"代码虐我千百遍,我待代码如初恋". 小Alan最近一直在忙着工作,已经很久没有写写东西来加深自己的理解了,今天来跟大家聊聊Java异常.Java异 ...

  6. 第11章 Java异常与异常处理

    1.Java异常简介 1.什么是异常异常出现的时候代码会无法正常运行下去,会产生各种问题2.捕捉异常的作用提早发现异常,方便查找问题,并给出解决方法3.Java中的异常1.Java中所有不正常的类都是 ...

  7. java 异常

    1.java异常 2.自定义抛出 3.运行时异常,程序有问题,让使用者可以改' ' 4.return  和  throw的区别 return 符合函数要求的值    throw  有问题的时候用它结束 ...

  8. 浅析Java中的final关键字

    浅析Java中的final关键字 谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来 ...

  9. 3.Java异常进阶

    3.JAVA异常进阶 1.Run函数中抛出的异常 1.run函数不会抛出异常 2.run函数的异常会交给UncaughtExceptionhandler处理 3.默认的UncaughtExceptio ...

随机推荐

  1. 读书笔记--SQL必知必会15--插入数据

    15.1 数据插入 使用INSERT语句将行插入(或添加)到数据库表.可能需要特定的安全权限. 插入完整的行 插入行的一部分 插入某些查询的结果 15.1.1 插入完整的行 要求指定表名和插入到新行中 ...

  2. 缩小窗口时CSS背景图出现右侧空白BUG的解决方法

    页面容器(#wrap)与页面头部(#header )为100%宽度.而内容的容器(#page)为固定宽度960px.浏览窗口缩小而小于内容层宽度时会产生宽度理解上的差异.如下图所示窗口宽度大于内容层宽 ...

  3. 《OOC》笔记(4)——自动化地将C#代码转化为C代码(结构版)

    <OOC>笔记(4)——自动化地将C#代码转化为C代码(结构版) 我在<C表达面向对象语言的机制——C#版>中已经说明了从C#到C的转换方法.这次看<OOC>也是想 ...

  4. ReSharper 配置及用法(转)

    1:安装后,Resharper会用他自己的英文智能提示,替换掉 vs2010的智能提示,所以我们要换回到vs2010的智能提示 2:快捷键.是使用vs2010的快捷键还是使用 Resharper的快捷 ...

  5. php代码优化,mysql语句优化,面试需要用到的

    首先说个问题,就是这些所谓的优化其实代码标准化的建议,其实真算不上什么正真意义上的优化,还有一点需要指出的为了一丁点的性能优化,甚至在代码上的在一次请求上性能提升万分之一的所谓就去大面积改变代码习惯, ...

  6. 『TCP/IP详解——卷一:协议』读书笔记——02

    2013-08-16 20:07:11 1.3 TCP/IP的分层 这是一个很好的图,要多看!!图上有些细节会在今后的笔记中提到,看不懂不必深究. IP是网络层上的主要协议,同时被TCP和UDP(这两 ...

  7. JSTL 标签库 使用

    标签库概要: 一.C标签库介绍 1.1.<c:> 核心标签库  JSTL 核心标签库(C标签)标签共有13个,功能上分为4类:1.表达式控制标签:out.set.remove.catch2 ...

  8. [POJ1338]Ugly Numbers

    [POJ1338]Ugly Numbers 试题描述 Ugly numbers are numbers whose only prime factors are 2, 3 or 5. The sequ ...

  9. .NET XML文件增删改查

    查询 采用的是DataSet 的 ReadXML方法. DataSet ds = new System.Data.DataSet(); ds.ReadXml("bdc.xml"); ...

  10. linux 编译内核[scripts/kconfig/dochecklxdialog] 错误

    administrator@ubuntu:~/linux-2.6.28-omap$ make menuconfig *** Unable to find the ncurses libraries o ...