捕获异常

  1. 捕获异常的基础用法
  2. 多catch语句
  3. finally语句
  4. 捕获多种异常

捕获异常的基础用法

捕获异常使用try...catch语句,把可能发生异常的代码放到try {...}中,然后使用catch捕获对应的Exception及其子类:

public class Main {
    public static void main(String[] args) {
        byte[] bs = toGBK("中文");
        System.out.println(Arrays.toString(bs));
    }

    static byte[] toGBK(String s) {
        try {
            // 用指定编码转换String为byte[]:
            return s.getBytes("GBK");
        } catch (UnsupportedEncodingException e) {
            // 如果系统不支持GBK编码,会捕获到UnsupportedEncodingException:
            System.out.println(e); // 打印异常信息
            return s.getBytes(); // 尝试使用用默认编码
        }
    }
}

如果我们不捕获UnsupportedEncodingException,会出现编译失败的问题:

public class Main {
    public static void main(String[] args) {
        byte[] bs = toGBK("中文");
        System.out.println(Arrays.toString(bs));
    }

    static byte[] toGBK(String s) {
        return s.getBytes("GBK");
    }
}

不能运行,因为编译器会报错,错误信息类似:Unhandled exception: java.io.UnsupportedEncodingException。这是因为String.getBytes(String)方法定义是:

public byte[] getBytes(String charsetName) throws UnsupportedEncodingException {
    ...
}

在方法定义的时候,使用throws Xxx表示该方法可能抛出的异常类型。调用方在调用的时候,必须强制捕获这些异常,否则编译器会报错。

调用方toGBK()方法,调用了String.getBytes(String)方法,所以在调用方toGBK()方法中必须捕获UnsupportedEncodingException。

toGBK()也可以不捕获它而是扔给更高层的调用方去处理。在定义处用throws表示toGBK()方法可能会抛出UnsupportedEncodingException,在更高层的main函数中,由于调用了toGBK()方法,所以必须捕获toGBK()方法throws的UnsupportedEncodingException。修改后代码如下:

public class Main {
    public static void main(String[] args) {
        try {
            byte[] bs = toGBK("中文");
            System.out.println(Arrays.toString(bs));
        } catch (UnsupportedEncodingException e) {
            System.out.println(e);
        }
    }

    static byte[] toGBK(String s) throws UnsupportedEncodingException {
        // 用指定编码转换String为byte[]:
        return s.getBytes("GBK");
    }
}

多catch语句

可以使用多个catch语句,每个catch分别捕获对应的Exception及其子类。JVM在捕获到异常后,会从上到下匹配catch语句,匹配到某个catch后,执行catch代码块,然后不再继续匹配。

简单地说就是:多个catch语句只有一个能被执行。例如:

public static void main(String[] args) {
    try {
        process1();
        process2();
        process3();
    } catch (IOException e) {
        System.out.println(e);
    } catch (NumberFormatException e) {
        System.out.println(e);
    }
}

存在多个catch的时候,catch的顺序非常重要:如下UnsupportedEncodingException异常是永远捕获不到的,因为它是IOException的子类。当抛出UnsupportedEncodingException异常时,会被catch (IOException e) { … }捕获并执行。

public static void main(String[] args) {
    try {
        process1();
        process2();
        process3();
    } catch (IOException e) {
        System.out.println("IO error");
    } catch (UnsupportedEncodingException e) { // 永远捕获不到
        System.out.println("Bad encoding");
    }
}

因此,正确的写法是把子类放到前面:

public static void main(String[] args) {
    try {
        process1();
        process2();
        process3();
    } catch (UnsupportedEncodingException e) {
        System.out.println("Bad encoding");
    } catch (IOException e) {
        System.out.println("IO error");
    }
}

finally语句

无论是否有异常发生,如果我们都希望执行一些语句,例如清理工作,怎么写?
Java的try ... catch机制还提供了finally语句,finally语句块保证有无错误都会执行。

public static void main(String[] args) {
    try {
        process1();
        process2();
        process3();
    } catch (UnsupportedEncodingException e) {
        System.out.println("Bad encoding");
    } catch (IOException e) {
        System.out.println("IO error");
    } finally {
        System.out.println("END");
    }
}

捕获多种异常

如果某些异常的处理逻辑相同,但是异常本身不存在继承关系,那么就得编写多条catch子句:

public static void main(String[] args) {
    try {
        process1();
        process2();
        process3();
    } catch (IOException e) {
        System.out.println("Bad input");
    } catch (NumberFormatException e) {
        System.out.println("Bad input");
    } catch (Exception e) {
        System.out.println("Unknown error");
    }
}

因为处理IOException和NumberFormatException的代码是相同的,所以我们可以把它两用|合并到一起:

public static void main(String[] args) {
    try {
        process1();
        process2();
        process3();
    } catch (IOException | NumberFormatException e) { // IOException或NumberFormatException
        System.out.println("Bad input");
    } catch (Exception e) {
        System.out.println("Unknown error");
    }
}

他の者にできたか?ここまでやれたか?この先できるか?いいや、仆にしかできない!

目录
×

喜欢就点赞,疼爱就打赏