一、异常概念
在使用计算机语言开发项目时,即使程序员把代码写得尽善尽美,在系统运行过程中仍会遇到一些问题,因为很多问题不是靠代码能够避免的,比如:用户输入数据的格式,读取文件是否存在,网络是否保持通畅等等。
异常: 在Java语言中,将程序执行中发生不正常的情况称为“异常”
Java程序在执行过程中所发生的异常事件可分为两类:
1)Error:Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。一般不编写针对性的代码进行处理
2)Exception:因为编程错误或偶然的外在因素导致的一般性问题,可以使用异常处理机制进行解决 。例如:数组下标越界,试图读取不存在的问题,网络连接中断
Error类型的异常我么无法控制,但是Expection类型的异常我们可以解决,对于这种异常,一般有两种解决办法:一是遇到异常就终止程序的运行。另一种是在编写程序时就考虑对异常的检测,异常信息的提示,以及异常的处理。
Throwable
类是我们异常体系中最大的类,它可以代指我们程序中遇到的异常,这个类下面有两个子类
1.Error
:Java虚拟机内部的问题,也有可能时我们代码书写的问题
2.Exception
:因编程问题或偶然情况导致的异常问题,这个类下面也有两个大的子类:
2.1RuntimeException
:运行时异常,在编译期间不强制要求处理的异常
2.2继承了Exception
但未继承或未间接RuntimeException
的子类:这种是编译时异常,我们在编写代码器间强制要求解决。
二、异常处理
2.1 异常捕获
Java编程语言使用异常机制为程序提供了错误处理能力。没有使用异常机制时,程序遇到异常,程序终止执行,不太友好。如果想在程序出现问题时,程序依然可以执行,就需要我们在编写代码时首先将异常处理机制写好,一旦发生异常,就会按照我们预定的处理机制执行。
例如:
try {
int parseInt = Integer.parseInt("a");
int b = 100;
int a = 0;
System.out.println(b/a);
} catch (ArithmeticException arithmeticException) {
System.out.println("0不能作为分母");
} catch (NumberFormatException numberFormatException) {
System.out.println("数字格式异常");
} catch (Exception e) {
System.out.println("系统忙");
}
- 将可能出现异常的代码放到try{}中, 运行时, 如果代码发成了异常的话,就会生成一个对应的异常类的对象.这个产生的异常对象会与catch的异常类型相匹配,匹配成功后就被 catch 捕获,然后运行catch{}中的代码, 一般catch中的代码为处理异常的代码, 比如返回异常的信息和返回异常的详细信息等. 一旦异常处理完成,就会跳出当前的try-catch结构,无论有没有发生异常finally中的代码都会最后被执行
catch多个异常类型的时候, 如果有子父类关系,小的范围写上面大的范围写下面; 如果没有子父类关系,谁在上谁在下无所谓。我们还可以在最后加上捕获Exception
,这样只要是程序导致的异常都会进行捕获,可以使得程序更加安全。
常用的异常对象处理方式: ① e.getMessage() ② e.printSrackTrace()
在try结构中生命的变量,在出了try结构以后,就不能在被调用。如果想避免这种情况,就需要在try之前声明变量并初始化,在try中赋值。
假如我们代码中某一行发生了异常且没有进行捕获的话,程序便会终止,后面的代码无法执行。
当我们捕获了这一异常的话,程序便会正常执行。
2.2 finally
finally代码块中的代码一定会执行,无论是否捕获异常,所以将必须要执行的代码逻辑放在finally代码块中
finally代码块不能单独使用,必须结合 try{}
或者 try { } catch() { }
2.3 throws
throws,定义一个方法的时候可以使用throws关键字声明,表示此方法不处理异常,而是交给调用方法进行处理。
任何方法都可以使用throws关键字生命异常类型,包括抽象方法
子类重写父类中的方法,子类方法不能抛出比父类类型更大的异常
使用了throws的方法,调用时必须处理声明的异常,要么使用try{}catch(){},要么继续使用throws声明
A方法调用B方法时,如果B方法内部捕获了异常,那么A方法是不知道的,所以我们都是在调用方法处进行异常的捕获,被调用方法只是进行异常的抛出。
2.4 throw
throw关键字用于显式抛出异常,抛出的时候是抛出的是一个异常类的实例化对象
在异常处理中,try语句要捕获的是一个异常对象,那么此异常对象也可以自己抛出。
2.5 throws和throw
throw用于方法体中,用来抛出一个实际的异常对象,使用throw后,要么使用try catch捕获异常,要么使用throws声明异常
throws用于方法声明处,用来声明该方法可能发生的异常类型,可以是多个异常类型,用来强制调用该方法时处理这些异常
抽象方法也可以使用throws
三、自定义异常
Java中提供了许多异常类供我们捕获异常。而实际的开发中,我们需要在满足某种条件的情况下抛出异常对象,而这种异常类Java中可能没有提供,这是我们便可以自定义异常类。
四、面试题
Java的异常处理机制?
Java异常处理机制可以是程序具有极好的容错性和健壮性。
Java的异常处理机制可以分为3部分,异常处理,抛出异常和异常跟踪栈。
在Java中异常处理语句是由try{}catch(){}finally{},我们可以使用try语句块包裹可能出错的业务代码,catch语句块用来捕获对应类型的异常,finally用来关闭资源。如果try语句块包裹的代码发生异常,系统会创建一个异常对象并交给JVM处理,然后JVM会寻找可以处理这个异常的catch块,并将异常对象交给对应的catch块处理。如果JVM没有找到可以处理异常的catch块,运行环境便会终止,程序会推出。若业务代码打开了某些资源,可以在finally代码块中进行关闭,因为finally语句块中的代码一定会执行(一般情况下:例如在try语句块还没开始程序就异常或者返回,又或者是断电)。
当程序发生异常时,系统会自动抛出异常。除此之外,Java也允许主动抛出异常,当业务代码中某些错误条件满足时,可以使用throw关键字抛出异常对象。这种情况下,方法不知道该如何处理异常,可以在方法声明位置使用throws关键字抛出可能会发生的异常,该异常会被交给JVM。程序在运行的时候,由于各个方法的调用从而形成方法调用栈,异常机制会使异常对象在方法中传播,而异常传播的方向和调用方法的方法相反,由被调用者传播向调用者,这样一级级最终会传播给main方法,如果依然没有处理,JVM会终止程序,并打印异常跟踪栈信息