Java异常机制
Java异常分类
异常表明程序运行发生了意外,导致正常流程发生错误,例如数学上的除0,打开一个文件但此文件实际不存在,用户输入非法的参数等。在C语言中我们处理这类事件一般是将其与代码正常的流程放在一起,通过判断条件让程序作出相应的操作,例如添加提示信息然后让程序返回一个错误码。在Java中引入了异常处理,可以帮助我们将程序的正常流程和错误处理分开。Java中所有的异常都继承自java.lang.Exception类。Throwable类又包含两个直接的子类,分别为Error和Exception,从这两个子类又分别生出一些新的异常类,如图所示:

Exception是从任何Java类库的方法(包括标准类库的方法和自己定义的类方法)以及运行时抛出异常的基类。它可以分为运行时异常(RuntimeException)和检查异常(Checked Exception)两种。对于检查异常Java编译器会检查它,编译器要求必须捕获(使用try-catch)或声明抛出这种异常(使用throws语句声明抛出),除了RuntimeException外的其他异常均为检查异常。对于RuntimeException在默认情况下会自动处理,例如除0操作,访问非法的数组下标等,所以一般不用捕获RuntimeException,但是如果是自己定义的异常则需要抛出。
Error表示程序中出现了严重的问题,一般需要终止程序,例如VirtualMachineError是Java虚拟机运行错误。Error与Exception的区别是Error和它的子类的对象不能被抛出,它也不需要抛出,因为一般遇到这类问题时都意味着程序需要中止。
Java内置异常
Java内置的一些异常都定义在java.lang中,标准的运行时异常一般是最常用的异常,因为java.lang是默认加载的,所以一般从RuntimeException继承来的异常都可以直接使用。Java内置的一些RuntimeException如下表:
| 异常 | 描述 | 
| ArithmeticException | 当出现异常的运算条件时,抛出此异常。例如,一个整数"除以零"时,抛出此类的一个实例。 | 
| ArrayIndexOutOfBoundsException | 用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引。 | 
| ArrayStoreException | 试图将错误类型的对象存储到一个对象数组时抛出的异常。 | 
| ClassCastException | 当试图将对象强制转换为不是实例的子类时,抛出该异常。 | 
| IllegalArgumentException | 抛出的异常表明向方法传递了一个不合法或不正确的参数。 | 
| IllegalMonitorStateException | 抛出的异常表明某一线程已经试图等待对象的监视器,或者试图通知其他正在等待对象的监视器而本身没有指定监视器的线程。 | 
| IllegalStateException | 在非法或不适当的时间调用方法时产生的信号。换句话说,即 Java 环境或 Java 应用程序没有处于请求操作所要求的适当状态下。 | 
| IllegalThreadStateException | 线程没有处于请求操作所要求的适当状态时抛出的异常。 | 
| IndexOutOfBoundsException | 指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出。 | 
| NegativeArraySizeException | 如果应用程序试图创建大小为负的数组,则抛出该异常。 | 
| NullPointerException | 当应用程序试图在需要对象的地方使用 null 时,抛出该异常 | 
| NumberFormatException | 当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。 | 
| SecurityException | 由安全管理器抛出的异常,指示存在安全侵犯。 | 
| StringIndexOutOfBoundsException | 此异常由 String 方法抛出,指示索引或者为负,或者超出字符串的大小。 | 
| UnsupportedOperationException | 当不支持请求的操作时,抛出该异常。 | 
CheckedException如下表所示:
| 异常 | 描述 | 
| ClassNotFoundException | 应用程序试图加载类时,找不到相应的类,抛出该异常。 | 
| CloneNotSupportedException | 当调用 Object 类中的 clone 方法克隆对象,但该对象的类无法实现 Cloneable 接口时,抛出该异常。 | 
| IllegalAccessException | 拒绝访问一个类的时候,抛出该异常。 | 
| InstantiationException | 当试图使用 Class 类中的 newInstance 方法创建一个类的实例,而指定的类对象因为是一个接口或是一个抽象类而无法实例化时,抛出该异常。 | 
| InterruptedException | 一个线程被另一个线程中断,抛出该异常。 | 
| NoSuchFieldException | 请求的变量不存在 | 
| NoSuchMethodException | 请求的方法不存在 | 
异常方法
Throwable类提供一些异常方法如下表所示:
| 序号 | 方法及说明 | 
| 1 | public String getMessage() | 
| 2 | public Throwable getCause() | 
| 3 | public String toString() | 
| 4 | public void printStackTrace() | 
| 5 | public StackTraceElement [] getStackTrace() | 
| 6 | public Throwable fillInStackTrace() | 
Java异常处理
Java处理异常机制包括抛出异常和捕获异常,抛出异常是指当一个方法出现错误引发异常时,这个方法需要创建一个异常对象,异常对象包含异常类型和一些异常信息,使用throw关键字实现,如果一个方法没有捕获检查异常,则次方法必须使用throws关键字声明,throws关键字用在方法签名的尾部,当有多个异常需要声明时用","隔开。捕获异常从字面理解就是抓住异常,只有在异常抛出时才能被捕获,捕获异常一般用try…catch…finally语句实现,当存在try块时,catch和finally语句必须再少存在一个。
使用throws抛出异常
如果一个方法可能会抛出一个异常,但是没法处理这个异常,例如汽车这个类在飞驰时抛锚了,它自己只能抛出此异常,不能处理,而需要靠开汽车的人来想办法修理。下面方法抛出一个异常
public class MyClazz {
    public static int calc() throws ArithmeticException {
        int a = 0, b = 10;
        return b/a;
    }
    public static void main(String[] args) {
        try {
             calc();
    } catch (ArithmeticException e) {
         System.out.println(“calc throws an ArithmeticException”);
        }
    }
}
可以看到calc方法本身只是在方法声明时加上了throws,它并不处理异常,实际上由调用它的函数处理异常。当然方法本身也是可以处理异常的,对于throws的使用如果异常时Error或者RuntimeException或者他们的子类,则可以不用使用throws关键字声明,这些异常会被自动抛出。对于Checked Exception一定要在方法中声明异常,可以使用try…catch语句捕获或者使用throws关键字在声明将其抛出。对于抛出的异常如果自己没有处理能力则由其调用者处理。
使用throw抛出异常
throw用于在方法中抛出异常,语法格式为throw new ExceptionName,使用例子如下:
public class ExceptionTest {
    public static void f() throws Exception {
        int i;
        for (i = 0; i < 6; i++) {
            if (i == 5) {
                throw new Exception();
            }
            System.out.println(i);
        }
    }
    public static void main(String[] args) {
        try {
            f();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
运行之后可以看到,当i=5时会抛出异常,此时异常被捕捉到然后打印方法的堆栈信息,当抛出异常之后,它之后的语句就不会再执行了,所以此时5没有打印出来。
try…catch…finally语句使用
try块用来执行正常的流程,catch用来捕获相关的异常,finally语句表示无论是否有异常被捕获都会执行。
public class ExceptionTest {
    class Exception1 extends Exception {}
    class Exception2 extends Exception {}
    public void f() throws Exception {
        int i;
        for (i = 0; i < 6; i++) {
            if (i == 5) {
                throw new Exception();
            }
            System.out.println(i);
        }
    }
    public void g() throws Exception1 {
        throw new Exception1();
    }
    public void h() throws Exception2 {
        throw new Exception2();
    }
    public static void main(String[] args) {
        ExceptionTest et = new ExceptionTest();
        try {
            et.f();
            et.g();
            et.h();
        } catch (Exception2 e) {
            e.printStackTrace();
        } catch (Exception1 e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("ExceptionTest finally");
        }
    }
}
执行发现,当f()方法抛出异常后g()和h()方法均不会被执行,此时他们抛出的异常都被屏蔽掉了,但是finally语句块还是会被执行。在网上截取了一张try catch finally语句块的执行流:

自定义异常
在Java中可以自定义异常,编写异常时要注意几点:
- 所有异常必须是Throwable的子类;
- 如果是一个检查性异常必须继承Exception;
- 如果是一个运行时异常必须继承RuntimeException;
class Exception1 extends Exception {
    String message;
    Exception1(String message) {
        this.message = message;
    }
    public String getMessage() {
        return this.message;
    }
}
class Exception2 extends Exception {
    String message;
    public Exception2(String message) {
        this.message = message;
    }
    public String getMessage() {
        return this.message;
    }
}
public class ExceptionClazz {
    public static void f() {
        try {
            g();
            throw new Exception1("f throw exception1");
        } catch (Exception1 e) {
            System.out.println(e.getMessage());
        } finally {
            System.out.println("f finally");
        }
    }
    public static void g() {
        try {
            h();
            throw new Exception2("g throw exception2");
        } catch (Exception2 e) {
            System.out.println(e.getMessage());
        } finally {
            System.out.println("g finally");
        }
    }
    public static void h() {
        try {
            throw new Exception();
        } catch (Exception e) {
            System.out.println("h throw a Exception");
        } finally {
            System.out.println("h finally");
        }
    }
    public static void main(String[] args) {
        f();
    }
}
最终打印为:
h throw a Exception
h finally
g throw exception2
g finally
f throw exception1
f finally
Java异常机制的更多相关文章
- 全面理解java异常机制
		在理想状态下,程序会按照我们预想的步骤一步一步的执行,但是即使你是大V,你也不可避免出错,所以java为我们提供了异常机制.本文将会从以下几个方面介绍java中的异常机制: 异常机制的层次结构 异常的 ... 
- Java 异常机制
		Java 异常机制 什么是异常 异常指不期而至的各种状况,如:文件找不到.网络连接失败.非法参数等.异常是一个事件,它发生在程序运行期间,干扰了正常的指令流程 为什么要有异常 什么出错了 哪里出错了 ... 
- 【55】java异常机制剖析
		一.为什么要使用异常 首先我们可以明确一点就是异常的处理机制可以确保我们程序的健壮性,提高系统可用率.虽然我们不是特别喜欢看到它,但是我们不能不承认它的地位,作用.有异常就说明程序存在问题,有助于我们 ... 
- Java异常机制及异常处理建议
		1.Java异常机制 异常指不期而至的各种状况,如:文件找不到.网络连接失败.非法参数等.异常是一个事件,它发生在程序运行期间,干扰了正常的指令流程.Java通过API中Throwable类的众多子类 ... 
- [Java学习笔记] Java异常机制(也许是全网最独特视角)
		Java 异常机制(也许是全网最独特视角) 一.Java中的"异常"指什么 什么是异常 一句话简单理解:异常是程序运行中的一些异常或者错误. (纯字面意思) Error类 和 Ex ... 
- Java异常机制简介
		什么是异常? 异常一般是指程序在编译期没有问题,但是在程序运行期出现的错误,一个程序会因为出现异常而终止运行,也就是我们常说的挂掉,在多线程下,异常只会影响所在的线程,对其他线程没有影响. Java异 ... 
- Java基础 --  深入理解Java异常机制
		异常指不期而至的各种状况,如:文件找不到.网络连接失败.非法参数等.异常是一个事件,它发生在程序运行期间,干扰了正常的指令流程.Java通 过API中Throwable类的众多子类描述各种不同的异常. ... 
- 一张图搞清楚Java异常机制
		下面是Java异常类的组织结构,红色区域的异常类表示是程序需要显示捕捉或者抛出的. Throwable Throwable是Java异常的顶级类,所有的异常都继承于这个类. Error,Excepti ... 
- Java异常机制,自定义异常以及spring boot异常设计方案
		异常机制: 异常概念 异常分类 异常的处理方法 自定义异常 springboot 的异常解决方案 
随机推荐
- android浮动搜索框
			android浮动搜索框的配置比较繁琐,需要配置好xml文件才能实现onSearchRequest()方法. 1.配置搜索的XML配置文件,新建文件searchable.xml,保存在res/xml ... 
- Azure平台 对Twitter 推文关键字进行实时大数据分析
			Learn how to do real-time sentiment analysis of big data using HBase in an HDInsight (Hadoop) cluste ... 
- WebService是什么
			Webservice的一个最基本的目的就是提供在各个不同平台的不同应用系统的协同工作能力. 其实WebService并不是什么神秘的东西,它就是一个可以远程调用的类,或者说是组件. 为什么要使用Web ... 
- 学编程,学单词.....在学习中积累自己的单词(不断更新__ing)
			可以去肆意大话天下,可以去小民一般的言语,但是一定要清楚,知识的积累,至于心中,即便你说这粗俗的话,你的个性,气质依旧在那,比如北大的那啥教师(心中的典范),也只有这样,你才能低至市井,上至高阁... ... 
- Text Justification [LeetCode]
			Problem Description:http://oj.leetcode.com/problems/text-justification/ Note: Just be careful about ... 
- js 格式验证总结
			1.身份证号验证 var Common = { //身份证号验证 IsIdCardNo: function (IdCard) { var reg = /^\d{15}(\d{2}[0-9X])?$/i ... 
- spring3表达式语言(SpEL)
			使用SpEl进行表达式操作,基本操作如下: <!--第一步,构建解析 --> ExpressionParser parser = new SpelExpressionParser(); & ... 
- 79. 212. Word Search *HARD* -- 字符矩阵中查找单词
			79. Word Search Given a 2D board and a word, find if the word exists in the grid. The word can be co ... 
- target不起作用了
			原因是 <a href="",target></a>中间多了个逗号. 
- Andriod使用webview控件往APP里内嵌网页
			转自博文:http://www.cnblogs.com/JuneZhang/p/4148542.html 1.布局文件片段:res-layout <WebView android:id=&quo ... 
