java的异常捕捉机制,try/catch用法及什么时候需要捕捉异常

异常时java里的一个重要组件之一,几乎所有的代码里面都会出现异常,为了保证程序在出现异常之后可以正常执行完毕,就需要进行异常处理。
异常类图片

所有的异常都是由Throwable继承而来,其中Error是无法有我们手动抛出异常的,一般情况下我们最关心的就是Exception,在Exception之下又分为两个分支,RuntimeException和IOException;
其中RuntimeException是用户在运行时可能发生也可能不发生的异常,可以对其不进行处理,当发生时虚拟机停止,而IOException是在编译阶段就需要我们去必须手动捕捉进行解决;

public static void code2() {
        File file = new File("D:\\ab.txt");
        try {
            FileInputStream inputStream = new FileInputStream(file);
            try{
                 throw new Exception ();
            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

此时一个try可以嵌套使用也可以拥有很多个catch,当拥有很多个catch时,是按照先后顺序执行的,需要注意的是应该把子类的catch放在前面,不然父类catch会将之后的子类catch覆盖,不会有任何输出;

public static int div(int a, int b) throws ArithmeticException {
        int c =0;
        try {
          c = a/b;
            return a / b;
        } catch (Exception e) {
            throw e;//被捕获异常重新抛出
        } finally {
            c=55;
            System.out.println(c);//55
        }
    }

如果遇到不想处理的异常可以利用throws抛给上一级有上一级处理,finally无论异常发不发生都会执行,但是它的执行顺序是发生在return之后的,也就是虽然c的值在finally中改变,但是却对return那个值不造成任何影响;
同时如果在finally中加入return的话,会覆盖之前定义的return

public static int div1(int a, int b)  {
        int c =0;
        try {
          c = a/b;
            return a / b;
        } catch (Exception e) {
            return 0;
        } finally {
            c=55;
            System.out.println(c);//55
            return c;//发生覆盖
        }
    }

除了使用java给我们提供的异常类以外,我们还可以通过继承两种父类:Exception、RuntimeException;来完成

class AddException extends Exception {
    public AddException(String msg) {
        super(msg);
    }
}

public class Test {
    public static void main(String[] args) throws Exception {
        int num1 = 20;
        int num2 = 30;
        if (num1 + num2 == 50) {
            throw new AddException("错误的相加操作");
        }
    }

这样就可以通过进行特殊需求判断时抛出需要的异常信息,比如此时就将两个数相加为50的数标记为了错误,抛出了自定义异常类AddException;

总的来说,除了IOException这一类在编译时需要抛出的异常来看,java的抛出异常就是为了在代码运行有错误时,不想只是单纯的从返回值甚至是程序停止时看出,应该让程序在此时输出更多的错误信息,这样可以将未知的错误捕捉进行捕捉,抛异常同样如此是为了可能发生的情况做准备,并不一定会执行;

public static void code9() {
        int i = 5;
        int j = 0;
        try{
            i++;//执行
            int c = i/j;
            j++;//不执行
        }catch (ArithmeticException e){
            e.printStackTrace();
        }
        System.out.println(i);//6
        System.out.println(j);//0
    }

注意当在try中发生异常后,就会自动跳转到catch语句,不会执行之后的语句,之后更不会回到try块之中,而是直接离开执行try之后的语句;