瞧一瞧,看一看!Java异常的捕获及处理

异常的基本概念

异常是导致程序中断运行的一种指令流,如果不对异常进行正确的处理,则可能导致程序的中断执行,所以在程序的设计中必须要考虑各种异常的发生,并正确的做好相应的处理,这样才能保证程序的正常执行。

异常的分类

异常分为严重异常-Error 和 一般异常,一般异常又分为运行时异常(RuntimeException)和 编译时异常(除了RuntimeException)。
运行时异常:不需要我们显式处理,我们也可以像编译时异常一样使用try…catch。
编译时异常:我们在执行程序之前,必须要处理的异常,如果不处理,程序将不能运行。
应注意:

  • 出现Error一般不做异常处理,因为是比较严重的问题,可能与代码没有关系。
  • 出现RuntimeException也不做异常处理,出现这种问题一般是程序设计不够严谨造成的问题。
  • 出现编译时异常我们必须马上做异常处理,否则代码将无法通过编译。

默认异常处理

案例一:

public class ExceptionDemo1 {
    public static void main(String[] args) {
        int a = 1;
        int b = 0;
        System.out.println(a / b);
        System.out.println("此处代码不执行");
    }
}

运行结果:
Exception in thread "main" java.lang.ArithmeticException: / by zero
程序出现问题后,控制台打印了错误信息,包括Exception的包名+类名,错误的描述,出现的位置。这些异常处理操作是JVM做的。即默认的异常处理方式是:
1、打印错误信息
2、结束程序

异常处理

两种处理方式:
1、try...catch...finally
2、throws
try…catch处理方式格式:

try{
	//有可能出现异常的代码
} catch(异常类 异常对象){
	//编写异常的处理语句
} catch(异常类 异常对象){
	//编写异常的处理语句
}...finally{
	//一定会运行到的程序代码
}

如果在try中出现了异常,则程序会自动跳转到catch语句中找到匹配的异常类型进行相应的处理。最后不管程序是否会出现异常,都会执行到finally语句,finally语句就是异常的统一出口。finally是可以省略的,则在catch()块运行结束后,程序会跳到try-catch块之后继续执行。
案例二:

public class ExceptionDemo2 {
    public static void main(String[] args) {
        int a = 1;
        int b = 0;
        try {
            System.out.println(a / b);
            System.out.println("此处代码不再执行");
        } catch (ArithmeticException ae) { //创建一个异常对象,捕获算术异常
            System.out.println("出现异常了:" + ae);
            System.out.println("除数不能是0");
        }
        System.out.println("程序结束");
    }
}

运行结果:

出现异常了:java.lang.ArithmeticException: / by zero
除数不能是0
程序结束

通过结果我们可以得出:通过try…catch处理异常,不但可以对异常进行一些自定义的处理,而且程序不会被停止,会继续运行。
多个异常的处理:
可以采用多个try-catch语句,也可以一个try,多个catch语句。以第二种方式为例。
案例三:

public class ExceptionDemo3 {
    public static void main(String[] args) {
        int a = 1;
        int b = 0;
        int[] c = {1, 2, 3};
        try {
            System.out.println(a / b);
            System.out.println(c[3]);
        } catch (ArithmeticException e) {
            System.out.println("除数不能为0");
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("数组越界");
        }
        System.out.println("程序结束!");
    }
}

当采用一个try多个catch时,如果try-catch补货到异常,会立即去catch匹配异常,如果匹配到,整个try-catch结构就会结束,try中剩余的语句将不再执行。

异常类的继承结构

在整个Java的异常结构中,有两个最常用的类,Exception和Error,这两个类都是Throwable的子类。
当我们不知道代码中的异常具体是哪个时,可以通过所有异常的父类Exception去匹配。
案例四:

public class ExceptionDemo4 {
    public static void main(String[] args) {
        method();
    }
    //多个异常的处理
    public static void method() {
        int a = 1 ;
        int b = 0 ;
        int[] c = {1, 2, 3};
        try {
            System.out.println(a / b);
            System.out.println(c[3]);    
        } catch (Exception e) {
            System.out.println("有异常");
        }
        System.out.println("程序结束!");
    }

案例五:

try {
			//可能出错的语句
        } catch (ArithmeticException e) {
            System.out.println("除数不能为0");
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("数组越界了");
        }catch(Exception e){
            System.out.println("程序出现异常");
        }

ArithmeticExceptionArrayIndexOutOfBoundsException,都属于Exception的子类,当try-catch中有多个异常捕获是,应注意:

  • 如果异常在继承体系中是平级关系,它们的前后不会影响最后的执行结果。
  • 如果异常在继承体系结构中属于父子关系,则父类一定要写在最后,否则子类异常不会被正常匹配到。

JDK7之后的异常处理方式:
格式:

try{
           ……
       }catch(异常类名1 | 异常类名2 | 异常类名3| ……  变量名 ){
           ……
       }

案例六:

public class ExceptionDemo5 {
    public static void main(String[] args) {
        int a = 1;
        int b = 0;
        int[] c = {1, 2, 3};
        try {
            System.out.println(a / b);
            System.out.println(c[3]);
        } catch (ArithmeticException | ArrayIndexOutOfBoundsException e) {
            System.out.println("有异常");
        }
        System.out.println("程序结束!");
    }
}

在使用此方法时应注意:多个异常必须是平级关系,否则会报错。而且对于不同的异常只有统一处理方式,不能区别处理。

异常处理时的注意事项:
在编写代码时,确定代码没有错误,但是被标红,这种情况可能是调用的某个方法存在编译时异常,必须在执行前进行异常处理。例如在格式化日期的parse方法中。
案例七:

public class ExceptionDemo6 {
    public static void main(String[] args) {
        String s = "2020-8-16 11:12:45";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Date date = sdf.parse(s);
            System.out.println(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

异常信息的输出方式:
在catch语句输出异常时,可以直接使用System.out.println(异常对象);也可以直接使用Exception类中的printStackTrace()方法输出异常信息,格式为e.printStackTrace();,打印出异常类名、异常信息及异常在程序中出现的位置。

Throwable

Throwable常用方法:
1、public String getMessage()获取异常信息
2、public String toString()获取异常信息和异常类名
3、public void printStackTrace获取出异常类名、异常信息及异常在程序中出现的位置
案例八:

public class ExceptionDemo6 {
    public static void main(String[] args) {
        String s = "2020-8-16";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Date date = sdf.parse(s);
        } catch (ParseException e) {
            System.out.println(e.getMessage());//Unparseable date: "2020-8-16"
            System.out.println(e.toString());//java.text.ParseException: Unparseable date: "2020-8-16"
            e.printStackTrace();
        }
    }
}

throws关键字
在定义一个方法时可以使用throws关键字声明,使用throws声明的方法表示此方法不处理异常,而交给方法的调用处进行处理。
throws 使用格式:

public 返回值类型 方法名称(参数列表...) throws 异常类1, 异常类2...{ }

运行时异常:异常抛出,调用者不用处理。
案例九:

public class ExceptionDemo7 {
    public static void main(String[] args) {
        method();
    //运行时异常
    public static void method() throws ArithmeticException {
        int a = 1;
        int b = 0;
        System.out.println(a / b);
    }
}

编译时异常:异常抛出,调用者必须处理。还应注意尽量不要在主方法上进行异常的抛出,这样的话,异常会交给JVM处理,即默认处理方式。
案例十:

public class ExceptionDemo8 {
    public static void main(String[] args) {
        try {
            method1();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        System.out.println("程序结束!");
    }
    //编译时异常
    public static void method1() throws ParseException {
        String s = "2020-8-16";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = sdf.parse(s);
        System.out.println(date);
    }
}

throw关键字
可以直接使用throw抛出一个异常,抛出时直接抛出异常类的实例化对象。使用位置在方法体内。

public class ExceptionDemo9 {
    public static void main(String[] args) {
        method();
    }
    public static void method() {
        int a = 1;
        int b = 0;
        if (b == 0) {
            throw new ArithmeticException();
        } else {
            System.out.println(a / b);
        }
    }
}

自定义异常

Java中提供的异常类有时很难满足需求,所以用户可以根据自己的需求定义自己的异常类。定义异常类时只需要继承Exception类即可。

public class StudentDemo {
    public static void main(String[] args) {
        //创建Scanner对象
        Scanner sc = new Scanner(System.in);
        //接收用户输入的数据
        System.out.println("请输入成绩:");
        int score = sc.nextInt();
        //校验成绩
        Teacher teacher = new Teacher();
        try {
            teacher.checkScore(score);
        } catch (MyException e) {
            e.printStackTrace();
        }
        System.out.println("程序结束");
    }
}

class Teacher {
    public void checkScore(int score) throws MyException {
        if (score < 0 || score > 100) {
            throw new MyException("成绩必须在0-100之间");
        } else {
            System.out.println("您输入的成绩合法!");
        }
    }
}

class MyException extends Exception {
    //构造方法
    //无参构造
    public MyException() {
    }
    //指定有参构造
    public MyException(String message) {
        super(message);//调用Exception类中有一个参数的构造方法,传递错误信息
    }
}

我是快斗,欢迎批评指正!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值