try-catch,throw和throws的使用

try…catch

try-catch,try即尝试,尝试能不能正常的走完整个作用域,如果不能则抛出一个异常。所以在try块里经常放上可能会抛出异常的程序段。而catch就是处理try里抛出来的异常,其中catch的参数列表接收的是一个异常的引用,是throw抛出来的异常的引用。

try-catch可以嵌套使用,以下是一个try-catch嵌套使用的例子:

public class exTest {
    public static void main(String[] args) {
        try {
            System.out.println("***外层try***");
            errorMethod();
        } catch (Exception e) {
            System.out.println("***外层catch" + e + "***");
        } finally {
            System.out.println("***外层finally***");
        }
    }

    private static void errorMethod() {
        try {
            System.out.println("***内层try***");
            int i = 0;
            int a = 100 / i;
        }catch (Exception e) {
            System.out.println("***内层catch,异常:" + e + "***");
        }finally {
            System.out.println("***内层finally***");
        }
    }
}

//output
***外层try***
***内层try***
***内层catch,异常:java.lang.ArithmeticException: / by zero***
***内层finally***
***外层finally***

若是注释掉内层catch,其他一样

public class exTest {
    public static void main(String[] args) {
        try {
            System.out.println("***外层try***");
            errorMethod();
        } catch (Exception e) {
            System.out.println("***外层catch" + e + "***");
        } finally {
            System.out.println("***外层finally***");
        }
    }

    private static void errorMethod() {
        try {
            System.out.println("***内层try***");
            int i = 0;
            int a = 100 / i;
        }finally {
            System.out.println("***内层finally***");
        }
    }
}

//output
***外层try***
***内层try***
***内层finally***
***外层catchjava.lang.ArithmeticException: / by zero***
***外层finally***

总结一个报错后的执行顺序


    try {
            //A  报错地方
            try {
                //B 
            } catch (Exception e) {
                //C  
            } finally {
                //D  
            }
            //E  
        } catch (Exception e) {
            //F
        } finally {
            //G
    }
  1. 内层A,E处抛出异常:由外层catch块捕获,并执行外层finally ;
  2. 内层B处抛出异常,且有一合适内层catch捕获在:执行内层finally,后执行E处 ;
  3. 内层B处抛出异常,但内层catch块没有合适处理程序:执行内层finally,搜索外层catch,找合适的,执行外层finally,此时不会执行E
  4. 内层C处抛出异常在:退出内层catch块,执行内层finally,搜索外层catch,找到合适,执行外层finally ;
  5. 内层D处抛出异常在:退出内层finally块,搜索外层catch,找到合适,执行外层finally。

总结:

1.try-catch 嵌套内层catch 可以捕获异常时,外层catch不会执行,但finally (多用于IO关闭)都会执行。

2.try-catch一般用在最上层的程序里,可以配合throws和throw再将异常抛给用户,这种情况会使上层代码中断。也可以不选择抛出,这种上层代码会继续运行。

3.被调用的方法如果有异常的可能可以通过throws抛给上层处理,不加try catch的情况如下会自动往上抛,加了try catch需要如上通过throw抛给上层程序。

throw

throw 即抛出一个异常,并获取这个异常的引用,这个异常会被抛到外部的环境,由外部环境进行处理。

throw 一般会用于程序出现某种逻辑时程序员主动抛出某种特定类型的异常。

throw跟try…catch…finally的对比:

try catch是直接处理,处理完成之后程序继续往下执行,try catch只能获取程序运行时引发的异常,而throw语句可以引发明确的异常。throw则是将异常抛给它的上一级处理,程序便不往下执行了。

class ZeroTest {
    public static void main(String[] args) {
        try{
            int i =100/0;
            System.out.print(i + System.lineSeparator());
        }catch(Exception e){
            System.out.print(1 + System.lineSeparator());
            throw new RuntimeException();
        }finally{
            System.out.print(2 + System.lineSeparator());
        }
        System.out.print(3);
    }
}

//output
1
2
Exception in thread "main" java.lang.RuntimeException
    at ZeroTest.main(exTest.java:8)

e、e.toString()、e.getMessage()和e.printStackTrace()

e

public class exTest {
    public static void main(String[] args) {
        try {
            errorMethod();
        } catch (Exception e) {
            System.out.println("***外层catch,异常:" + e + "***");
        }
    }

    private static void errorMethod() {
        try {
            int i = 0;
            int a = 100 / i;
        }catch (Exception e) {
            System.out.println("***内层catch,异常:" + e + "***");
        }
    }
}

//output
***内层catch,异常:java.lang.ArithmeticException: / by zero***

e.toString

public class exTest {
    public static void main(String[] args) {
        try {
            errorMethod();
        } catch (Exception e) {
            System.out.println("***外层catch,异常:" + e + "***");
        }
    }

    private static void errorMethod() {
        try {
            int i = 0;
            int a = 100 / i;
        }catch (Exception e) {
            System.out.println("***内层catch,异常:" + e.toString() + "***");
        }
    }
}

//output
***内层catch,异常:java.lang.ArithmeticException: / by zero***

和e一样,因为printIn方法隐式帮e转换为String了,不用我们转

e.getMessage

public class exTest {
    public static void main(String[] args) {
        try {
            errorMethod();
        } catch (Exception e) {
            System.out.println("***外层catch,异常:" + e + "***");
        }
    }

    private static void errorMethod() {
        try {
            int i = 0;
            int a = 100 / i;
        }catch (Exception e) {
            System.out.println("***内层catch,异常:" + e.getMessage() + "***");
        }
    }
}

//output
***内层catch,异常:/ by zero***

信息少了一部分。

printStackTrace

public class exTest {
    public static void main(String[] args) {
        try {
            errorMethod();
        } catch (Exception e) {
            System.out.println("***外层catch,异常:" + e + "***");
        }
    }

    private static void errorMethod() {
        try {
            int i = 0;
            int a = 100 / i;
        }catch (Exception e) {
            System.out.println("***内层catch,异常:" + e + "***");
            e.printStackTrace();
        }
    }
}

//output
***内层catch,异常:java.lang.ArithmeticException: / by zero***
java.lang.ArithmeticException: / by zero
    at exTest.errorMethod(exTest.java:13)
    at exTest.main(exTest.java:4)

throws

throws并不是抛出一个实际的Exception而是一个异常声明,它声明这个方法可能会抛出一个异常,注意是可能,所以在没有异常的情况下也是可以用throws的,而throws本身的作用也是用来提高程序的健壮性,反过来,如果这个方法的的确有一个异常,那么编译器会强制让加上throws异常声明。

通常throws是写在参数列表的后面,表明这个方法有可能会抛出一个异常。

class A{

    public void f() throws Exception{

    }
}

   转载规则


《try-catch,throw和throws的使用》 锦泉 采用 知识共享署名 4.0 国际许可协议 进行许可。
  目录