Java中的异常详解

Java中的异常详解



前言

生活中的异常:

  1. 每天上班坐公交车去,正常的话半个小时,但是有时候会出现堵车(一定会出现的),或者遇到交通事故等,就有可能造成上班迟到的情况,这就是一种异常情况。
  2. 睡觉的时候,睡的正香,突然一个电话过来,被吵醒了。
  3. 在大街上走着,突然被绊倒了。

概述

Java中的异常:
  • 异常是指在程序的运行过程中所发生的不正常的事件,它会中断正在运行的程序。简单来说就是程序出现了不正常的情况。
  • 异常本质就是Java当中对可能出现的问题进行描述的一种对象体现。
常见异常:
  • 除数不能为0异常(ArithmeticException)
  • 空指针异常(NullPointException)
  • 数组越界异常(ArrayIndexOutOfBoundsException)
  • 类型转换异常(ClassCastException)

Throwable类

Throwable 类是 Java 语言中所有错误或异常的超类。

1556195855322

成员方法:
  • public String getMessage():返回此 throwable 的详细消息字符串
  • public String toString():获取异常类名和异常信息。
  • public void printStackTrace():获取异常类名和异常信息,以及异常出现在程序的位置。
  • public void printStackTrace(PrintStream s):通常用该方法将异常内容保存在日志文件中,以便查阅。
Error和Exception
  1. Error:称为错误,由Java虚拟机生成并抛出,程序对其不做处理。

  2. Exception:所有异常类的父类,其子类对应了各种各样可能出现的异常事件,一般需要用户显示的声明或捕获。


Exception类

所有异常类的父类,其子类对应了各种各样可能出现的异常事件,一般需要用户显示的声明或捕获。

运行时期异常(RuntimeException):

  • 运行时期异常,又称为非受检异常,RuntimeException及其所有子类都是运行时期异常。

编译时期异常:

  • 不是继承自RuntimeException的Exception的子类都成为编译时期异常

异常处理

如果我们不做任何处理,异常将会交由虚拟机来处理。

虚拟机的处理方式:

  • 把异常的名称,异常出现的位置,异常原因,等信息输出打印在控制台,并同时将程序停止执行。

思考:

在实际开发当中显然直接将应用程序挂掉的这种方式是不可取的,就算程序有异常,我们也理应让程序继续执行下去,提高用户体验。那我们又该怎么做呢?

分析

异常的执行流程:

  1. 程序执行到错误行,系统会创建一个异常对象,并且抛给我们

    ArithmeticException exp = new ArithmeticException("/by zero");

    ​ throw exp;

  2. 程序进入catch块进行逐个匹配,匹配成功,程序执行catch块代码

    ArithmeticException ae = exp;

    ​ Exception e = exp;

  3. 匹配失败,交给jvm处理

jvm默认是如何处理异常的?

  1. 打印错误信息

    a.异常名称 java.lang.ArithmeticException

    b.异常的消息 / by zero

    c.异常所发生的方法位置 at com.sxt.exceptiondemo.ExceptionDemo02.main

    d.异常所在Java文件中 ExceptionDemo02.java

    e.异常发生行号 14

  2. 终止程序

    System.exit(0);

处理异常的标准方式:

  1. 能够显示处理的尽量显示处理,提高程序的可读性。
  2. 但是一定要在异常处理的最后加上 父类Exception处理。
处理方式
  1. try…catch…finally
  2. throws抛出异常
  • try…catch…finally

    • try…catch…finally的处理格式:
      异常处理的格式:
      try{
      //放置程序可能出现问题的代码
      }catch(异常类 异常名){
      //这里放置异常处理的代码
      } finally{
      //释放资源
      }

    • 多个异常的处理
      格式:try{

      }catch(异常类名 变量名) {

      }catch(异常类名 变量名) {

      } catch…

      排列catch 语句的顺序:

      1. 先子类后父类
      2. 发生异常时按顺序逐个匹配
      3. 只执行第一个与异常类型匹配的catch语句

Throws和Throw

throws关键字
  • 概述:在定义一个方法的时候可以使用throws关键字声明,使用throws声明的方法表示此方法不处理异常,而交给方法的调用者进行处理。
  • 格式: [修饰符] 返回值类型 方法名(参数列表) [throws 异常类1,异常类2…]{
    }

注意:
1、如果一个方法声明的是编译时期异常,则在调用这个方法之处必须处置这个异常(谁调用谁处理)。
2、重写一个方法时,它所声明的异常范围不能被扩大

 public static int calc() throws ArithmeticException{
               int a = 10;
               int b = 0;
               int result = a/b;
               return result;
       }
throw关键字
  • 在方法代码中主动抛出一个异常。如果方法代码中自行抛出的异常是编译时期异常,则这个方法要用throw关键字声明这个异常。
public static void method2() throws ArithmeticException {
               int a = 10;
               int b = 0;
               if (b == 0) {
                   // throw
                       throw new ArithmeticException("除数为0了!");
               }
               System.out.println(a/b);
       }
throws和throw的区别
  1. throws用在方法声明后面,跟的是异常类名,throw用在方法体内,跟的是异常对象名。
  2. throws可以跟多个异常类名,用逗号隔开,throw只能抛出一个异常对象名。
  3. throws表示抛出异常,由该方法的调用者来处理,throw表示抛出异常,由方法体内的语句处理。
  4. throws表示出现异常的一种可能性,并不一定会发生这些异常,throw则是抛出了异常,执行throw则一定抛出了某种异常。

finally关键字

finally修饰的代码块一定会被执行,除非在执行到finally之前程序异常退出或者调用了系统退出的方法。

finally用于释放资源,在IO流操作和数据库操作中会见到。

注意:

finally碰到return时finally一定会执行,那执行顺序?

public class ExceptionDemo09 {
	public static void main(String[] args) {

		System.out.println(test()); // 4 3
	}

	public static int test() {
		int x = 1;
		try {
			System.out.println(x++ / 0); // 2
		} catch (Exception e) {
			x++; //
			return x; // return 3;
		} finally {
			++x; // 4
			System.out.println(x); // 4
		}
		return x;
	}
}

分析:

在try语句中,在执行return语句时,要返回的结果已经准备好了,就在此时,程序转到finally执行了。

在转去之前,try中先把要返回的结果存放到不同于x的局部变量中去,执行完finally之后,在从中取出返回结果。

因此,即使finally中对变量x进行了改变,但是不会影响返回结果。它应该使用栈保存返回值。


自定义异常

在工作中有许多异常需要自己写。那如何写一个异常呢?

  • 编写一个分数必须在0-100分之间的异常,并且使用这个异常。

步骤:

  • 定义一个异常继承Throwable或者Exception或者RuntimeException

  • 编写构造方法

    • 带参

    • 无参

public class ExceptionDemo {
       public static void main(String[] args) {
               Scanner input = new Scanner(System.in);
               System.out.println("请输入一个分数:");
               double score = input.nextDouble();
               Teacher teacher = new Teacher();
               try {
                       System.out.println(teacher.isBetween0To100(score) ? "分数合法" : "分数不合法");
               } catch (ScoreException e) {
//                        e.printStackTrace();
                       System.err.println(e.getMessage());
               } catch (Exception e) {
                       e.printStackTrace();
               } finally {
                       input.close();
               }
               System.out.println("分数批改完毕!");
                               
       }
}

class ScoreException extends Exception{
       
       public ScoreException(){}
       
       public ScoreException(String message) {
               super(message);
       }
}

class Teacher{
       
       public boolean isBetween0To100(double score) throws ScoreException{
               if (score > 100 || score < 0) {
                       throw new ScoreException("分数必须在0-100分之间!!!");
               }
               return true;
       }
}


以上

@Fzxey

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值