Java异常详解

摘要 (来自于 Java编程思想)

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

改进的错误恢复机制是提高代码健壮性的最强有力的方式。错误恢复在我们所编写的每一个程序中都是基本的要素,但是在 Java 中它显得格外重要,因为 Java 的主要目标之一就是创建供他人使用的程序构件。发现错误的理想时机是在编译阶段,也就是在你试图运行程序之前。然而,编译期间并不能找出所有的错误,余下的问题必须在运行期间解决。这就需要错误源能通过某种方式,把适当的信息传递给某个接受者–该接受者将知道如何正确处理这个问题。

异常往往能降低错误代码的复杂度的。如果不使用异常,那么就必须检查特定的错误,并在程序中的许多地方去处理它。而如果使用异常,那就不必在方法调用处进行检查,因为异常机制将保证能够捕获这个错误。总结,与普通的错误处理方法相比,异常处理方式使程序更加简洁、清晰,同时方便我们定位错误和处理错误。

Java 异常分类

936870-20170709120346087-1351539391

  1. 所有异常的父类都是Throwable。
  2. Error表示Java系统中出现了一个非常严重的异常错误,并且这个错误可能是应用程序所不能恢复的,例如LinkageError,或 ThreadDeath 等。

Java Exception和Error区别

Exception:

  1. 可以是可被控制(checked)或者不可控制(unchecked);
  2. 表示一个由程序员导致的错误;
  3. 应该在应用程序级被处理;

Error:

  1. 总是不可控制的(unchecked);
  2. 经常用来表示系统错误或者底层资源错误;
  3. 如果可能的话,应该系统级被捕捉;

Java 检查异常、非检查异常、运行时异常、非运行时异常的区别

Java的异常(Throwable,Exception和Error的父类)分为检查异常和非检查的异常。

检查异常:

就是编译器要求你必须处理的异常。比如我们在编程某个文件的读写时,编译器要求你必须对某段代码进行try…catch…或者throws exception,这就是检查异常。即在程序运行之前,编译器就会要求处理的异常被称为检查异常。

检查异常包括除了RuntimeException与其派生类(子类),以及错误(Error)之外,其它差不多都是检查异常。

非检查异常:

编译器不要求强制处置的异常,虽然可能出现错误,但是我不会在编译的时候检查。这类异常我们一般是不处理的,因为很难判断会出现什么问题,而且有些异常你也无法在编译时处理,比如空指针。

非检查异常包括 RuntimeException及其子类,以及错误(Error)

Exception异常进行划分,它可分为运行时异常和非运行时异常

运行时异常:

都是RuntimeException类及其子类异常,如NullpointerException(空指针异常)、IndexArrayOutRangeException(下标越界异常)等,这些异常都是非检查异常,程序可以选择捕获处理,也可以不处理。这些异常一般有程序逻辑错误引起,程序应该尽可能从逻辑角度避免这类异常的发生。

运行时异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现运行时异常,即使没有try…catch…捕获它,也没有throws声明抛出它,也会编译通过。

常见的运行时异常:NullPointerException、ArrayIndexOutOfBoundsException、IndexOutOfBoundsException、ArrayIndexOutOfBoundsException、NumberFormatException、IllegalArgumentException等等。

非运行时异常:

是RuntimeException意外的异常,类型上都属于Exception类及其子类。属于必须在编译时处理的异常,否则就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常,一般情况不要自定义检查异常。

Java 自定义异常

用户自定义异常属于非运行时异常,需要在程序编译时处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

public class Main {

public static void main(String[] args) {
try {
new Main().age(16);
} catch (IllegalAgeException e) {
e.printStackTrace();
}
}

private void age(int age) throws IllegalAgeException{
if (age < 18) {
throw new IllegalAgeException("");
}
System.out.println("age = [" + age + "]");
}
}

class IllegalAgeException extends Exception {

public IllegalAgeException() {
this("");
}

public IllegalAgeException(String message) {
super("年龄不合法");
}
}

Java throw关键字和throws关键字区别

  1. throws抛出的是可能出现的异常,需要用户手动处理异常,throw是明确程序这个地方需要抛出指定的异常对象。
  2. throws出现在方法函数头;而throw出现在函数体。
  3. throws表示出现异常的一种可能性,并不一定会发生这些异常;throw则是抛出了异常,执行throw则一定报出了某种异常。
  4. 两种都是消极处理异常的方式,这里的消极并不是说这种方式不好,只是抛出或者可能抛出异常,但是不会有函数本身去处理异常,真正的处理异常由函数的上层调用处理。
    1
    2
    3
    4
    5
    6
    7
    8
    throw 语法:
    throw 异常对象
    throw new IllegalArgumentException(" u can't ...");

    throws 是方法可能会抛出的异常的声明。
    throws 语法:
    [(修饰符)(返回值)(方法名)([参数列表])[thows (异常类)]{...}
    public void doA(int a) throws ExceptionA{....}

捕获异常

try{}catch{}finally{} 常见使用形式:

1
2
3
4
5
try{} catch{}

try{} finally{}

try{} catch{} finally{}

finally 关键字的特点及作用

  1. 特点被 finally 控制的语句一定会执行。特殊情况:在执行到finally之前jvm推出了(比如System.exit(0)),finally块语句将不会被执行
  2. 作用 一般在IO流操作或者数据库操作最后释放资源。
  3. 即使有return关键字,程序也会在返回之前执行finally代码块。
1
2
3
4
5
6
7
8
9
10
11
12
    public static void main(String[] args) {

try {
System.out.println(1/0);
}catch (Exception e){
System.out.println("除数不可以为0");
// System.exit(0);//退出JVM虚拟机
return;
}finally {
System.out.println("看看执行了没有");
}
}

打印结果:

除数不可以为0

看看执行了没有

Process finished with exit code 0

参考资料

https://www.cnblogs.com/yiwangzhibujian/p/7141390.html

https://www.cnblogs.com/sishuiliuyun/p/4421767.html

https://www.cnblogs.com/oukele/p/10035238.html

《Java编程思想》

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×