Java之异常处理


2018/12/26 Java

# 异常处理

异常处理常见手段: try catch finally throws

# try catch

  • 将可能抛出异常的代码块放在try代码块里

  • 如果try里没有异常,就回顺序往下执行,并且不执行catch块中的代码

  • 如果try存在异常,try 里的代码会立即终止,程序流程会运行到对应的catch块中,在catch块中还可以自定义语句,来应对产生的异常

  • e.printStackTrace(); 会打印出方法的调用痕迹

    try{
        .....
    } catch(Exception e){
        .....
    }
    
    1
    2
    3
    4
    5

# 使用异常的父类进行catch

所有的异常都是Exception的子类,所以如果不知道try块会发生什么异常,可以用Exception父类来接收异常

File f= new File("d:/LOL.exe");

try{
    System.out.println("试图打开 d:/LOL.exe");
    new FileInputStream(f);
    System.out.println("成功打开");
}
    
catch(Exception e){
    System.out.println("d:/LOL.exe不存在");
    e.printStackTrace();
}
1
2
3
4
5
6
7
8
9
10
11
12

# 多异常捕捉办法1

  • 有的时候一段代码会抛出多种异常

  • 解决办法之一是分别进行catch

    示例:

    try{
        ......
    }
    catch(Exception1 e){
      e.printStackTrace();
    }
    catch(Exception1 e){
      e.printStackTrace();
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

# 多异常捕捉办法2

另一个种办法是把多个异常,放在一个catch里统一捕捉

catch (FileNotFoundException | ParseException e){
1

这种方式从 JDK7开始支持,好处是捕捉的代码更紧凑,不足之处是,一旦发生异常,不能确定到底是哪种异常,需要通过instanceof 进行判断具体的异常类型 当然如果对不同异常的处理方法一致,也可以不用写if判断

try {
    ......
} catch (Exception1 | Exceptione2 e){
    if (e instanceof Exception1)
        ....
    if (e instanceof Exception2)
        ....

    e.printStackTrace();
}
1
2
3
4
5
6
7
8
9
10

# Finally

无论是否出现异常,finally中的代码都会被执行

try{
    .....
} catch(Exception e){
    .....
} finally{
    System.out.println("无论你怎么样,我都会被执");
}
1
2
3
4
5
6
7

# throws

敲!以下都是重点! 举个栗子: 主方法调用method1 method1调用method2 method2中打开文件

method2中有异常需要处理 但是method2不打算处理,而是把这个异常通过throws抛出去,抛给method1 那么method1就会接到该异常。 处理办法也是两种,要么是try catch处理掉,要么也是抛出去。 method1选择本地try catch住 一旦try catch住了,就相当于把这个异常消化掉了,主方法在调用method1的时候,就不需要进行异常处理了

package exception;
 
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
 
public class TestException {
 
    public static void main(String[] args) {
        method1();
 
    }
 
    private static void method1() {
        try {
            method2();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
 
    }
 
    private static void method2() throws FileNotFoundException {
 
        File f = new File("d:/LOL.exe");
 
        System.out.println("试图打开 d:/LOL.exe");
        new FileInputStream(f);
        System.out.println("成功打开");
 
    }
}
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
30
31
32
33

# throw和throws的区别

throws与throw这两个关键字接近,不过意义不一样,有如下区别:

  1. throws 出现在方法声明上,而throw通常都出现在方法体内。
  2. throws 表示出现异常的一种可能性,并不一定会发生这些异常;throw则是抛出了异常,执行throw则一定抛出了某个异常对象。

# 异常分类

总体上异常分三类:

  1. 错误(Error),是程序无法处理的错误,表示运行应用程序中较严重问题。
  2. 运行时异常(RuntimeException),运行的时候才会被检查出来的异常
  3. 非运行时异常(编译异常),编译的时候就出现的异常,即编译不通过

注意:异常和错误的区别:异常能被程序本身可以处理,错误是无法处理。

科普: Java之所以会设计运行时异常的原因之一,是因为下标越界,空指针这些运行时异常太过于普遍,如果都需要进行捕捉,代码的可读性就会变得很糟糕。

# Throwable

Throwable是类,Exception和Error都继承了该类 所以在捕捉的时候,也可以使用Throwable进行捕捉 如图: 异常分Error和Exception Exception里又分运行时异常和可查异常。

Throwable

# 自定义异常

  • 自定义异常的实现,通常就是提供一个构造方法。
  • 其实很多常见异常都是提供一个新的构造方法,比如: ClassNotFoundException等
  • 异常对象本身没有实际功能,只是一个标识,让你明白你具体是出现了哪个异常
    • 比如:ClassNotFoundException和PointNullException,都能抛出相同的异常,只是类名不一样,这样你就能区分出现了哪种异常

# 创建自定义异常

代码如下:

//这里继承的Exception(编译异常)也可以换成RuntimeException(运行时才能被检查到的异常),具体可以根据可以根据业务需求来决定使用哪个
public class MyException extends Exception
{
    public MyException(){
        super();
    }
    public MyException(String message){
        //有异常时一般会给个提示信息,就是这个message
        super(message);
    }
}

1
2
3
4
5
6
7
8
9
10
11
12

# 使用自定义异常

一般情况如下:

pubic class Test { 
    //这里的throws代表有可能会发生异常,如果有就抛出MyException
    public method() throws MyException{
        //一般在这里做一个判断,如果出现了你自定义的xxx,就会抛出异常
        if(xxx){
            //这里的throw是直接抛出异常,并且new一个MyException对象,再给个提示参数
            throw new MyException("这里可以写一些异常的提示信息,也可以不写");
        }   
        //如果没有以上异常,就可以在下面执行你想要执行的语句
        public static void xxxxxx....
    }
}
1
2
3
4
5
6
7
8
9
10
11
12

# JDK1.7新特性

  • try后面可以加括号,里面放的一般都是实现了closable()接口的类

  • 这样的作用是:try完{}里面的内容后会自动关闭()里面的连接

    例如:流的连接,或者数据库的连接

    try(FileInputStream fis = new FileInputStream(f)){
        .....
    }catch(Exception e){
        e.printStackTrace();
    }
    
    1
    2
    3
    4
    5

# 调试之debug

debug:调试是程序员编码过程中找逻辑错误的一个重要手段 断点:

Initializing...

山楂树之恋
程佳佳