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