详解Java中的异常机制:运行期异常、编译器异常及如何自定义异常
文章目录
- 前言
- 一、异常概述及分类
- 1.异常概述
- 2.异常的继承结构
- 3.异常的继承机构图
- 二、运行期异常-RuntimeException
- 1.JVM如何默认处理异常
- 2.try...catch的方式处理单个异常
- 3.try...catch的方式处理多个异常
- 4.代码示例
- 三、编译期异常-非RuntimeException及其子类
- 1.编译器异常的处理方式一(==抓==)
- 2.编译器异常的处理方式二(==抛==)
- 四、finally关键字和throw关键字
- 1.finally关键字
- 2.throw关键字
- 2.throws与throw的区别
- 五、自定义异常
- 六、异常的注意事项(针对编译器异常)
- 总结
前言
首先举一个现实生活中的例子,带大家理解异常。
小李是一个骑行爱好者,有一天他骑着自行车去西藏旅行。
一种情况:骑着骑着车轱辘坏了,是个大的问题,该问题他没有能力解决不了。(error)
另一种情况:车胎漏气了,是个小问题,该问题他有能力解决,但可以不解决。(运行期exception)
另一种情况:出门前,他检查出手刹松了,该问题他必须解决,才能上路。(编译器exception)
一、异常概述及分类
1.异常概述
- 异常就是Java程序运行过程中出现的错误。
- Java中有一个类Throwable类用于描述,错误和异常。
2.异常的继承结构
- Error错误
严重性无法解决的问题。(车轱辘飞了) - Exception异常
一般性可解决的问题。
- 编译器异常:发生在编译器期间,必须要处理。(手刹松了)
- 运行期异常:发生在运行期间,选择处理或不处理。(车胎漏气)
3.异常的继承机构图
二、运行期异常-RuntimeException
1.JVM如何默认处理异常
首先我们演示一个运行期异常。
代码:
public class 运行期异常 {public static void main(String[] args) {int a=1;int b=0;System.out.println(a / b);System.out.println("继续运行");}
}
执行结果:
- 我们没有处理运行期异常,默认交由JVM处理,JVM处理异常的方法是:打印异常的信息,然后退出JVM,不执行接下来的操作。
2.try…catch的方式处理单个异常
我们对JVM默认处理异常的方式不满意,希望异常不影响接下来代码的运行,我们可以适用**try…catch**捕获异常,不交由JVM处理。
- 格式
try {可能出现问题的代码 ;}catch(异常类型 变量名){针对问题的处理 ;}
- 代码示例
public class 运行期异常 {public static void main(String[] args) {int a=1;int b=0;//试图捕获可能出现的异常//try里面的代码:有可能出现异常的代码,不一定必须存在异常//catch(异常类型 异常变量名) :一旦try里面发生了catch中所捕获的异常类型,catch里面的代码就会执行。所以catch里面就放我们处理具体处理异常的操作。try {System.out.println(a / b);}catch (ArithmeticException e){System.out.println("初始为0");}System.out.println("继续运行");}
}
- 注意事项
- try中的代码越少越好
- catch中要做处理,哪怕是输出一条语句,不要将异常信息隐藏
3.try…catch的方式处理多个异常
当程序中出现多个异常时,我们可以使用多个catch进行异常的捕获。
- 多个异常时并列关系,放置顺序无所谓,如果异常类有父子关系,父类要放后面。
- 对于始料不及的异常,我们可以最后使用所有异常的父类Exception来捕获。(但是我们最好能够明确代码中可能出现的异常,不建议使用该方法)
代码示例:
public class 运行期异常2 {public static void main(String[] args) {int [] arr={1,2,3};//存在角标越界异常,是运行期异常try {arr[10] = 20;int a=10/0;arr = null;System.out.println(arr.length);//注意:如果捕获的异常不是出现的异常的情况,仍然是交由JVM处理}catch (ArrayIndexOutOfBoundsException a){//调用该方法可以打印详细的异常信息a.printStackTrace();}catch (ArithmeticException e){System.out.println("除数为0的异常");}catch (Exception c){System.out.println("其他异常");}System.out.println("继续执行");}
}
//!!!注意代码的执行顺序:捕获到try中的第一个异常,并使对应的catch进行捕获处理后,下一步不再执行try内的代码,而是执行程序接下来的代码。
4.代码示例
需求:用户输入一个整数,如果不是整数需要重新输入
- 调用scanner方法:调用hasNextInt()方法进行判断
public class 运行期异常的举例 {public static void main(String[] args) {while(true){Scanner scanner = new Scanner(System.in);System.out.println("请输入一个整数");//调用hasNextInt()方法实现if(scanner.hasNextInt()){int i = scanner.nextInt();System.out.println(i);System.out.println("输入正确");break;}else {System.out.println("请重新输入");}}}
}
- 使用try…catch实现
public class 运行期异常的举例 {public static void main(String[] args) {while(true){Scanner scanner = new Scanner(System.in);System.out.println("请输入一个整数");try {int i = scanner.nextInt();System.out.println(i);break;//通过该代码我们更好的了解catch如何使用,但是我们通常是输出异常信息} catch (InputMismatchException e) {System.out.println("输入有误,请重新输入");}}}
}
三、编译期异常-非RuntimeException及其子类
1.编译器异常的处理方式一(抓)
- 使用try…catch自己捕获处理
代码示例:
public class 编译器异常处理方式1 {public static void main(String[] args) {SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");//编译器异常必须处理,处理方式有两种//1.使用try...catch自己捕获处理try {Date date=simpleDateFormat.parse("2020202-1");}catch (ParseException p){p.printStackTrace();}System.out.println("继续执行");}
}
执行效果:
2.编译器异常的处理方式二(抛)
- 采用throws抛异常,甩锅给调用者,谁调用谁处理。
代码示例1:main方法抛异常,交由JVM处理异常
public class 编译器异常处理方式2 {//2.采用throws抛异常,甩锅给调用者,谁调用谁处理。//一般甩给main方法就不再甩了,如果继续甩到虚拟机接下来的代码就无法执行了。所以一般在main方法中捕获异常。public static void main(String[] args) throws ParseException {SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");Date date = simpleDateFormat.parse("202101-23");System.out.println("继续执行");}}
代码示例2:main方法抓异常
public class 编译器异常处理方式2 {public static void main(String[] args) {//main方法调用了,即将存在编译器异常的代码甩给了main方法//此时main方法可选择抛异常或者抓异常//抛异常:交给jvm处理,不再执行接下来的代码//抓异常:执行接下来的代码(一般需求需要抓)try {show();} catch (ParseException e) {e.printStackTrace();}System.out.println("继续执行");}public static void show() throws ParseException {SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd");Date d=s.parse("202020-2");}
}
四、finally关键字和throw关键字
1.finally关键字
- 用在try…catch…语句中来释放资源,其特点是始终被执行。
- 代码示例:
public class 关键字finally {public static void main(String[] args) {try {System.out.println(1/0);}catch (Exception e){System.out.println("catch代码执行了");//catch里面是try里面发生了所捕获的异常,那么catch里面的代码才会执行}finally {//不管try里面有没有遇到异常,finally里面的代码都会执行//常用于善后处理工作System.out.println("finally内的代码执行了");}}
}
2.throw关键字
- 在功能方法内部出现某种情况,程序不能继续运行,需要进行跳转时,就用throw把异常对象抛出。
- 代码示例:
public class 关键字throw {//throws 对编译器异常,进行抛出,抛给调用者去处理//throw 用在方法内部,对异常进行抛出public static void main(String[] args) {double r = division(12, 0);System.out.println("继续执行");System.out.println(r);}private static double division(int a, int b) {double r=0;//一旦判断除数为0if(b==0){//使用throw抛出异常,后续代码不再执行throw new ArithmeticException("除数为0");}else{r=a/b;}return r;}
}
- 注意
使用throw抛出异常,代码将不再执行。
2.throws与throw的区别
- throws
- 用在方法声明后面,跟的**异常类名**
- 可以跟多个异常类名,用逗号隔开
- 表示抛出异常,由该方法的调用者来处理
- throws表示出现异常的一种可能性,并不一定会发生这些异常
- throw
- 用在方法体内,跟的是**异常对象名**
- 只能抛出一个异常对象名
- 这个异常对象可以是编译期异常对象,可以是运行期异常对象
- 表示抛出异常,由方法体内的语句处理
- throw则是抛出了异常,执行throw则一定抛出了某种异常
五、自定义异常
- 因为在以后的开发过程中,我们可能会遇到各种问题,而Jdk不可能针对每一种问题都给出具体的异常类与之对应, 为了满足需求,我们就需要自定义异常。
代码示例1:银行取款余额不足异常
public class 自定义异常 {static int money = 100;public static void main(String[] args) {withdrawal();}
//取款的方法private static void withdrawal() {Scanner scanner = new Scanner(System.in);System.out.println("请输入你的取款金额");int num = scanner.nextInt();//取款金额小于账号余额if(num<=money){money-=num;System.out.println("取款成功");}else{//自定义异常抛出throw new NoMoneyException("余额不足异常");}}
}
//自定义余额不足的异常,继承java中的异常类
class NoMoneyException extends RuntimeException{public NoMoneyException() {super();}public NoMoneyException(String message) {super(message);}
}
代码示例2:学生成绩输出异常
public class 自定义异常之成绩非法异常 {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);System.out.println("请输入要录入的成绩");int i = scanner.nextInt();if(i>=0&&i<=100){System.out.println("成绩录入成功");}else{throw new ScoreException("成绩有误");}}
}
//自定义异常
class ScoreException extends RuntimeException{public ScoreException() {super();}public ScoreException(String message) {super(message);}
}
所谓自定义异常也就是创建我们自定义的异常类继承Java中的异常类,并在合理的处抛出异常满足程序需求即可。
六、异常的注意事项(针对编译器异常)
- 子类在重写父类方法时,父类方法没有抛出异常,子类就不能抛出异常
- 如果父类抛出异常,子类在重写该方法时,可以抛出与父类方法一样的异常或者该异常的子类,也可以不抛异常,自己捕获。
- 子类抛出的异常,不能比父类大只能是父类异常或该异常的子类。
总结
通过本文我们详细的了解了Java中的异常机制,其实在我们实际开发中遇到运行期异常,只需要选中我们认为可能会出现问题的代码,按住快捷键**ctrl+alt+t** 捕获处理即可。对于编译器异常,按住快捷键**alt+enter**,根据需求选择抛异常或者抓异常即可。
详解Java中的异常机制:运行期异常、编译器异常及如何自定义异常相关推荐
- 根据实例详解Java中的反射机制
概念: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java ...
- java 反射机制_详解Java中的反射机制的优缺点
一.什么是反射? 对于程序员来说,应该很少需要直接使用反射工具:之所以在语言中提供它们,是为了支持其他Java特性,比如对象序列化.Java Beans以及RMI.还有就是在很多框架中,也是应用到了反 ...
- java runnable 异常_详解Java中多线程异常捕获Runnable的实现
详解Java中多线程异常捕获Runnable的实现 1.背景: Java 多线程异常不向主线程抛,自己处理,外部捕获不了异常.所以要实现主线程对子线程异常的捕获. 2.工具: 实现Runnable接口 ...
- java io字符输出流_灵魂一击!详解Java中的IO输入输出流
什么是流?流表示任何有能力产生数据的数据源对象或者是有能力接收数据的接收端对象,它屏蔽了实际的I/O设备中处理数据的细节. IO流是实现输入输出的基础,它可以很方便地实现数据的输入输出操作,即读写操作 ...
- java同步异步调用_详解java 三种调用机制(同步、回调、异步)
1:同步调用:一种阻塞式调用,调用方要等待对方执行完毕才返回,jsPwwCe它是一种单向调用 2:回调:一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口: 3:异步调用:一种类似消 ...
- java lock unlock_详解Java中的ReentrantLock锁
ReentrantLock锁 ReentrantLock是Java中常用的锁,属于乐观锁类型,多线程并发情况下.能保证共享数据安全性,线程间有序性 ReentrantLock通过原子操作和阻塞实现锁原 ...
- java static 函数_详解java中的static关键字
Java中的static关键字可以用于修饰变量.方法.代码块和类,还可以与import关键字联合使用,使用的方式不同赋予了static关键字不同的作用,且在开发中使用广泛,这里做一下深入了解. 静态资 ...
- java中的静态变量的作用域_详解JAVA中static的作用
1.深度总结 引用一位网友的话,说的非常好,如果别人问你static的作用:如果你说静态修饰 类的属性 和 类的方法 别人认为你是合格的:如果是说 可以构成 静态代码块,那别人认为你还可以: 如果你说 ...
- java 死锁 内存消耗_详解Java中synchronized关键字的死锁和内存占用问题
先看一段synchronized 的详解: synchronized 是 java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 一.当两个并 ...
- java comparator相等_详解Java中Comparable和Comparator接口的区别
详解Java中Comparable和Comparator接口的区别 发布于 2020-7-20| 复制链接 摘记: 详解Java中Comparable和Comparator接口的区别本文要来详细分析一 ...
最新文章
- gd mysql_简单的图形计数器需要MYSQL,GD的支持_MySQL
- 如何借助高考热点,微信公众号两天疯狂引流2万+
- Ubuntu16.04 搭建SVN服务器(建立版本仓及import和checkout代码)
- MySQL error 1477_mysql_error.md
- 内存的使用和优化的注意事项
- win10树莓派改ip_用树莓派制作温湿度服务器
- JavaScript 调用 Windows Win32 API
- 【C++】黑马程序员 C++学习课程—C++基础入门
- 1万小时缔造的世界第一程序员
- 概率论:古典概型与伯努利概型
- 神经网络预测结果分析,神经网络怎么预测数据
- 洗头冲水时冲下好些头发,我是要秃了吗?
- C 二维数组,以及自定义二维数组
- 鸿蒙修复了蓝牙麦克风问题吗,手机变传声器、麦克风?华为P40的隐藏功能你知道吗?...
- 【数据结构】— 「时间复杂度」与「空间复杂度」
- 华科2020计算机专业录取线,华中科技大学2020录取分数线是多少
- BIM模型一键输出 3D Tiles (for Cesium) 和 glTF/blg
- MLDLRL:MLDL相关概念的原始英文解释——对理解最初的ML和DL的相关概念的定义非常有用
- 5G NR CSI-RS介绍(2)-- TRS
- □ 影片名:《拳霸2冬阴功》(20240) 在线播放