异常时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之后的语句;