异常: 是阻止当前方法或作用域继续执行的问题,在程序中导致程序中断运行的一些指令。
异常结构图:
异常最顶层是Object(所有类的父类)
Throwable类:是所有错误或异常的超类,直接继承Object类
Error:通常这样的问题属于虚拟机底层内部的问题,通常在写程序时不关注,也无法去处理。
Exception:重点关注类,程序本身抛出的异常,能抓住并能处理的异常
Exception 分受检异常和非受检异常
受检异常(Checked Exception):编译期检查,在调用抛出这个异常的方法时,必须显示的使用try…catch…
非受检异常(RuntimeException):运行期检查,在调用抛出这个异常的方法时,可以不用显示的使用try…catch…
常见的异常类:
ArithmeticException(数学运算异常)
ArrayIndexOutOfBoundsException (数组下标越界异常)
NullpointerException(空指针异常)
InputMismatchException(输入不匹配异常)
ClassNotFoundException(指定的类不存在)
ClassCastException(数据类型转换异常)
DataFormatException(数据格式化异常)
异常会导致程序中断,无法继续运行。在开发中,我们需要把可能出现异常的代码使用try语句块包裹起来,处理异常可以让程序保持运行状态。
try与catch关键字
在程序中出现异常,就必须进行处理,处理格式如下:
try(...){//JDK1.7以后直接释放资源
//有可能发生异常的代码段
}catch(异常类型 对象){
//异常的处理操作
}catch(异常类型 对象){
//异常的处理操作
}...
finally{
//异常的统一出口
}
catch可以有多个,顺序为从子类到父类,小的放前面,大的放后面
异常处理过程分析:
1、一旦产生异常,则系统会自动产生一个异常类的实例化对象。
2、此时如果存在了try语句,则会自动找到匹配的catch语句执行,如果没有异常处理,则程序将退出,并由系统报告错误。
3、所有的catch根据方法的参数匹配异常类的实例化对象,如果匹配成功,则表示由此catch进行处理。
finally关键字:
在进行异常的处理之后,在异常的处理格式中还有一个finally语句,那么此语句将作为异常的统一出口,不管是否产生了异常,最终都要执行此段代码。
throw与throws关键字:
throws关键字主要在方法的声明上使用,表示方法中部处理异常,而交给调用处处理。实际上对于java程序来讲,如果没有加入任何的异常处理,默认由jvm进行异常的处理操作。
throw关键字表示在程序中手动抛出一个异常,因为从异常处理机制来看,所有的异常一旦产生之后,实际上抛出的就是一个异常类的实例化对象,那么此对象也可以右throw直接抛出。
异常处理的语法规则:
1、try语句不能单独存在,可以和catch、finally组成try…catch…finally、try…catch、try…finally三种结构,catch语句可以有一个或多个,finally语句最多一个,try、catch、finally这三个关键字均不能单独使用。
2、try、catch、finally三个代码块中变量作用域分别独立而不能相互访问
3、多个catch块时候,java虚拟机会匹配其中一个异常类或其子类,就执行这个catch块,而不会再执行别的catch块。
try、catch、finally、throw与throws代码综合实例:
import java.util.InputMismatchException;
import java.util.Scanner;
public class TryCatchTest {
public static void main(String[] args) {
//div(10,0);
//method();
// try{
// div2(20,0);
// }
// catch(Exception e){
// e.printStackTrace();
// }
// System.out.println("over");
input();
}
private static void div(int num1,int num2) {
int[] arr = {1,2,3,4,5};
try {
System.out.println(arr[4]);
arr = null;
System.out.println(arr.length);
int result = num1/num2;
System.out.println("result ="+result);
}catch(ArithmeticException e){//数学算术异常
System.out.println("除数不能为0");
}catch(ArrayIndexOutOfBoundsException e){//
System.out.println("数组下标越界");
}catch(NullPointerException e){//
System.out.println("空指针异常");
}catch(Exception e){//
System.out.println("出错了");
}finally{
System.out.println("程序执行完成");
}
System.out.println("程序结束");
}
private static int method() {
int a = 10;
int b = 5;
try{
System.out.println("a ="+a);
System.out.println("b ="+b);
int c = a/b;
System.out.println("a/b ="+c);
return c;
}catch(Exception e){
//代码测试时使用
e.printStackTrace();
}finally{
System.out.println("finally");
}
return -1;
}
private static int div2(int a, int b)throws ArithmeticException{
try{
int c = a/b;
return c;
}catch(ArithmeticException e){
throw new ArithmeticException("除数不能为0");
}finally{
System.out.println("运行结束");
}
}
private static void input(){
//eclipse下ctrl+shift+o自动导包
Scanner input = new Scanner(System.in);
try {
int num = input.nextInt();
System.out.println(num);
}catch(InputMismatchException e) {
System.out.println("输入不匹配");
}
}
}
自定义异常
在java中,已经提供了很多的异常类的定义,但是我们在实际项目开发中,可能需要使用一些自己的异常类,那么可以通过继承Exception类或已有的异常类的方式完成一个自定义异常类的操作。
在使用自定义异常时,根据实际的业务要求,来决定使用哪个作为父类
assert关键字,表示断言
当程序执行到某个固定位置的时候,程序中的某个变量的取值肯定是预期的结果,那么这种操作可以使用断言完成。
断言的操作语法:
assert 表达式;