1 异常的概念

  1. 程序在执行过程中出现非正常线性,导致JVM非正常停止
  2. 异常不是语法错误

2 异常的分类

  1. Throwable是所有错误或异常的超类
  2. ··········Exception是编译期间异常(写代码时IDE会报错)
  3. ····················RuntimeException时运行期异常,程序运行时出现的问题
  4. ··········Error错误 必须修改代码才能继续执行

3 异常的产生过程

  1. 例如在某个方法体中,代码的不当操作导致了异常,运行程序时,JVM会检测出异常。
  2. JVM会根据异常产生的原因创建一个异常对象,包含异常产生的内容、原因和位置。
  3. 如果程序的方法体中没有在try-catch中定义异常处理逻辑,那么JVM就会把异常对象抛出给调用者该方法的main来处理这个异常。
  4. JVM接收到异常对象以红色字体打印在控制台并终止程序。(中断处理)

4 处理异常的方式

  1. throws虚拟机处理异常:中断程序,抛出错误,打印在控制台
  2. try-catch自己定义异常处理逻辑:程序可以继续执行

4.1 throw关键字

作用:在指定方法中抛出指定异常

使用格式:throw new xxxException(“异常产生原因”)

注意事项

  • 必须写在方法内部
  • new的对象要是Exception 或 Exception的子类
  • 如果抛出指定的异常对象,必须处理这个异常对象。
  • 如果创建的时RuntimeException或其子类,默认交给JVM处理(打印异常对象,中断程序)
  • 如果创建的时编译异常,就必须处理这个异常,必须throws或者try-catch

小贴士:必须首先对方法传递来的参数进行合法性校验,如果参数不合法,必须抛出异常,告知方法调用者,传递的参数有问题。

示例
运行时异常:NullPointerException

public class ThrowException {public static void main(String[] args) {//      int[] arr = null;int arr [] = {1,2,3};int element = getElement(arr, 10);System.out.println(element);}public static int getElement(int[] arr, int index){if(arr == null){throw new NullPointerException("传递的数组值是null");//空指针异常是运行期异常 默认交给JVM处理}if(index < 0 || index > arr.length){throw new ArrayIndexOutOfBoundsException("数组越界");}//运行期异常int element = arr[index];return element;}
}

4.2 Objects非空判断

Objects类的静态方法

public static <T> T requireNonNull(T obj) {if (obj == null)throw new NullPointerException()  ;return obj;
}

简化非空判断

public static void main(String[] args) {method(null);}public static void method(Object obj){Objects.requireNonNull(obj,"传递对象为空");}

4.3 throws声明异常

异常处理的第一种方式,交给别人处理

作用:当方法内部抛出异常对象时,必须处理异常对象,可以使用throws关键字处理,会把异常对象抛给方法调用者处理,自己不处理,交给他人处理,最终交给JVM处理。(JVM中断处理

使用方式:在方法声明时使用

注意

  • 必须写在方法声明处
  • 必须是Exception或其子类
  • 抛出多个异常,声明处要声明多个异常,如果是父子异常,声明父异常即可
  • 调用了声明异常的方法必须处理声明的异常。throws抛出最终交给JVM处理或者try-catch定义异常处理逻辑。

编译时异常:FileNotFoundException

    public static void main(String[] args) throws FileNotFoundException {method("c:\\d.txt");}public static void method(String filename) throws FileNotFoundException {if(!filename.equals("c:\\\\a.txt")){throw new FileNotFoundException("文件路径错误");}}


FileNotFoundException extends IOException extends Exception

    public static void main(String[] args) throws IOException {readFile("c:\\a.doc");}public static void readFile(String filename) throws IOException {if(!filename.endsWith(".txt")){throw new IOException("文件后缀不对");}}

4.4 try-catch捕获异常

异常处理的第二种方式,自己处理,程序不中断

public static void main(String[] args) throws IOException {try{readFile("d:\\a.tx");}catch (IOException e){System.out.println("文件后缀有误");}System.out.println("程序不中断,后续代码继续执行");}public static void readFile(String filename) throws IOException{if(!filename.endsWith(".txt")){throw new IOException("文件后缀有误");}System.out.println("读取文件");}

4.5 Throwable类中三个异常处理方法

  • String getMessage()

打印Message: throw new IOException(Message);

public static void main(String[] args) {try{readFile("d:\\a.tx");}catch (IOException e){System.out.println(e.getMessage());}System.out.println("程序不中断,后续代码继续执行");}public static void readFile(String filename) throws IOException{if(!filename.endsWith(".txt")){throw new IOException("文件后缀有误");}System.out.println("读取文件");}


  • String toString()

重写Object类的toString

public static void main(String[] args){try{readFile("d:\\a.tx");}catch (IOException e){System.out.println(e.toString());}System.out.println("程序不中断,后续代码继续执行");}public static void readFile(String filename) throws IOException{if(!filename.endsWith(".txt")){throw new IOException("文件后缀有误");}System.out.println("读取文件");}


  • void printStackTrace()
public static void main(String[] args) {try{readFile("d:\\a.tx");}catch (IOException e){e.printStackTrace();}System.out.println("程序不中断,后续代码继续执行");}public static void readFile(String filename) throws IOException{if(!filename.endsWith(".txt")){throw new IOException("文件后缀有误");}System.out.println("读取文件");}

4.6 finally代码块

public static void main(String[] args){try {readFile("d:\\a.tx");} catch (IOException e) {e.printStackTrace();} finally {System.out.println("异常出现后依旧需要执行的代码");}System.out.println("程序不中断,后续代码继续执行");}public static void readFile(String filename) throws IOException{if(!filename.endsWith(".txt")){throw new IOException("文件后缀有误");}System.out.println("读取文件");}

4.7 多异常捕获

分别捕获,分别处理

public static void main(String[] args) {int[] arr = {1,2,3};List<Integer> list = new ArrayList<>();list.add(1);try{System.out.println(arr[3]);}catch (ArrayIndexOutOfBoundsException e){e.printStackTrace();}try{System.out.println(list.get(1));}catch (IndexOutOfBoundsException e){e.printStackTrace();}System.out.println("后续代码继续执行...");}


一次捕获,多次处理

public static void main(String[] args) {try{int[] arr = {1,2,3};List<Integer> list = new ArrayList<>();System.out.println(arr[3]);list.add(1);System.out.println(list.get(1));}catch (ArrayIndexOutOfBoundsException e){e.printStackTrace();}catch (IndexOutOfBoundsException e){e.printStackTrace();}System.out.println("后续代码继续执行...");}


注意事项:一个try多个catch,catch中的异常变量如果有父子关系,子类异常变量必须写在上面,否则会报错。(XXXException has already been caught)


一次捕获,一次处理

public static void main(String[] args) {try {int[] arr = {1, 2, 3};List<Integer> list = new ArrayList<>();System.out.println(arr[3]);list.add(1);System.out.println(list.get(1));}catch (Exception e){e.printStackTrace();}System.out.println("后续代码继续执行...");}

运行时异常被抛出可以不处理。即不捕获也不声明抛出。

如果finally有return语句,永远返回finally中的结果,避免该情况。

如果父类抛出了多个异常,子类重写父类方法时,抛出和父类相同的异常或者是父类异常的子类或者不抛出异常。

父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常。此时子类产生该异常,只能捕获处理【try-catch】,不能声明抛出。

5 自定义异常

  • 自定义异常类一部都是以Exception结尾
  • 必须继承Exception(编译期异常,要么try-catch要么throws)或者继承RuntimeException(运行期异常交给JVM中断处理)

模拟注册操作

  1. 定义异常类 继承Exception
public class RegisterException extends Exception {public RegisterException() {super();}public RegisterException(String message) {super(message);}
}
  1. 定义测试类

throws

public class Register {static String[] usernames = {"张三","李四","王五"};public static void main(String[] args) throws RegisterException {System.out.print("请输入待注册用户名:");Scanner sc = new Scanner(System.in);String username = sc.next();checkUserName(username);System.out.println("恭喜,注册成功!");}//继承Exception是编译期异常 throws 处理public static void checkUserName(String name) throws RegisterException {for(String n: usernames){if(n.equals(name)){throw new RegisterException("该用户名已注册");}}}
}

try-catch

public class Register {static String[] usernames = {"张三", "李四", "王五"};public static void main(String[] args) {System.out.print("请输入待注册用户名:");Scanner sc = new Scanner(System.in);String username = sc.next();try {checkUserName(username);} catch (RegisterException e) {e.printStackTrace();return;}System.out.println("恭喜,注册成功!");}//继承Exception是编译期异常 throws 处理public static void checkUserName(String name) throws RegisterException {for(String n: usernames){if(n.equals(name)){throw new RegisterException("该用户名已注册");}}}
}


  1. 定义异常类 继承自RuntimeException
public class RegisterException extends RuntimeException {public RegisterException() {super();}public RegisterException(String message) {super(message);}
}
  1. 定义测试类:不需要处理运行期异常
public class Register {static String[] usernames = {"张三","李四","王五"};public static void main(String[] args){System.out.print("请输入待注册用户名:");Scanner sc = new Scanner(System.in);String username = sc.next();checkUserName(username);System.out.println("恭喜,注册成功!");}//继承RuntimeExceptionqpublic static void checkUserName(String name) throws RegisterException {for(String n: usernames){if(n.equals(name)){throw new RegisterException("该用户名已注册");//抛出给JVM处理}}}
}

【Java】如何理解Java中的异常机制?相关推荐

  1. 详解Java中的异常机制:运行期异常、编译器异常及如何自定义异常

    文章目录 前言 一.异常概述及分类 1.异常概述 2.异常的继承结构 3.异常的继承机构图 二.运行期异常-RuntimeException 1.JVM如何默认处理异常 2.try...catch的方 ...

  2. Java——深入理解Java异常体系

    Java--深入理解Java异常体系 参考文章: (1)Java--深入理解Java异常体系 (2)https://www.cnblogs.com/wugongzi/p/11858228.html 备 ...

  3. 再次理解STM32中的堆栈机制

    再次理解STM32中的堆栈机制 刚拿到STM32时,你只编写一个死循环 void main() { while(1); }BUILD://Program Size: Code=340 RO-data= ...

  4. java 异常 理解_java中的异常理解

    java异常是java提供的用于处理程序中错误的一种机制. 所谓错误是指在程序运行的过程中发生的一些异常事件(如:除0溢出,数组下标越界,所要读取的文件不存在). 设计良好地程序应该在程序异常发生时提 ...

  5. Java在远程方法调用中运用反射机制

    我们将介绍反射机制在网络编程中的应用,实现如何在客户端通过远程方法调用服务器端的方法. 假定在服务器端有一个 HelloService 接口,该接口具有 getTime() 和 echo() 方法,具 ...

  6. 初探JAVA代码在虚拟机中的运行机制

    前言 从这篇文章开始,后面我们将持续介绍JAVA虚拟机的工作原理.作为一名Android程序员,我们都知道Java代码有很多种运行方式,比如:可以在命令行中运行,可以在开发工具中运行,可以以jar文件 ...

  7. Java - 深入理解Java中的逃逸分析

    在Java的编译体系中,一个Java的源代码文件变成计算机可执行的机器指令的过程中,需要经过两段编译,第一段是把.java文件转换成.class文件.第二段编译是把.class转换成机器指令的过程. ...

  8. 跟着 Event loop 规范理解浏览器中的异步机制

    原文发自我的 GitHub blog,欢迎关注 前言 我们都知道 JavaScript 是一门单线程语言,这意味着同一事件只能执行一个任务,结束了才能去执行下一个.如果前面的任务没有执行完,后面的任务 ...

  9. 深入理解CV中的Attention机制之SE模块

    CV中的Attention机制汇总(一):SE模块 Squeeze-and-Excitation Networks 论文链接:Squeeze-and-Excitation Networks 1. 摘要 ...

最新文章

  1. 串口监视软件_ESP32 Arduino教程:软件重置
  2. 受小动物大脑结构启发,研究人员开发出新的深度学习模型:更少神经元,更多智能...
  3. 佛门的七众弟子指的是哪些呢?
  4. 百度地图描绘轨迹html,百度地图API 绘制轨迹历史
  5. 数据库中的二级索引_普通索引_辅助索引
  6. 怎么判断tcp重组完成_网络工程师(8):TCP为什么可靠
  7. SQL http://www.myfeng.cn/?T3009
  8. jspstudy启动mysql失败_解决Mysql5.7.17在windows下安装启动时提示不成功问题
  9. JDK下载与安装详细步骤
  10. 【转】使用chrome插件Page Monitor监控网页内容变化
  11. 学不会PDF裁剪与PDF拆分?6个方法包你轻松学会
  12. 盘点那些年火过的php建站系统
  13. html第三章练习1:音乐排行榜
  14. 从技术雷达看​DevOps的十年——容器技术和微服务
  15. .7z.001,.7z.002这样的文件如何解压
  16. linux在root安装软件,避免使用root安装软件
  17. cmd命令行窗口调整大小
  18. 华为机试【连续出牌数量】
  19. Spring Data JPA 4.方法定义规范
  20. 智融SW6206、SW3516、SW3522、SW2303等快充市场方案应用

热门文章

  1. 我做技术的这十年,我不做技术的这一年~
  2. Modbus协议概念最详细介绍
  3. alloca函数的风险_alloca的函数范围中的goto是否有效?
  4. div不继承父类样式_Python编程思想(27):类的继承
  5. MySQL基本操作指令
  6. react 网易云音乐实战项目笔记
  7. 指令系统——数据寻址(1)(详解)
  8. LeetCode 2022春季赛 1. 宝石补给
  9. LeetCode 1712. 将数组分成三个子数组的方案数(前缀和 + 二分查找)
  10. LeetCode 815. 公交路线(最少换乘,BFS)