Java学习24--异常

异常

软件运行过程中的各种意料之外叫做Exception,比如要读取的文件找不到,准备联网发现没网,等着int参数来了个String

注意Error和exception不一样,error错的比较猛,一般是直接把JAVA整个搞崩了,比如内存空间异常等等,JVM只好终止线程,这一般都是大错了。Exception一般是程序员脑子暂时抽风了,修修改改程序还能救回来。

举例,method a 和b互相无限调用对方,陷入无限循环。运行程序,观察系统输出什么。

package exception;public class Demo01 {public static void main(String[] args) {new Demo01().a();}public void a(){b();}public void b(){a();}
}

运行结果:

观察到系统输出了一句StackOverflowError这意思是stack内空间耗尽了,因为我们运行了一个没有终止条件的无限循环(记住做循环或者递归,一定要有可触发的程序终止条件)。


Exception in thread "main" java.lang.StackOverflowErrorat exception.Demo01.a(Demo01.java:8)at exception.Demo01.b(Demo01.java:11)at exception.Demo01.a(Demo01.java:8)at exception.Demo01.b(Demo01.java:11)N行循环

再举一个例子,除法分母是0,这在数学计算上本身就是不允许的。观察程序运行结果。


package exception;public class Demo01 {public static void main(String[] args) {System.out.println(6 / 0);}
}

运行结果:
观察到程序出了关键字“ArithmeticException: / by zero”这句的意思就是,数学错误: 除以零。通过观察输出的字样,程序员可以快速找到程序出错的位置。

Exception in thread "main" java.lang.ArithmeticException: / by zeroat exception.Demo01.main(Demo01.java:5)Process finished with exit code 1

异常处理的思维

Java异常处理是Java编程语言中用于处理程序中可能出现的错误或异常情况的一种机制。它提供了一种结构化的方式来响应和处理运行时错误,使程序能够在遇到问题时相对优雅的输出有效提示,而不是程序直接崩溃。

JAVA把异常当object处理,定义一个java.lang.Throwable 作为所有异常class的超类class

JAVA API已经提前定义了许多异常class,分为两大类:错误Error和异常Exception

在这里插入图片描述

如上图,错误error class:JAVA直接崩了,表示JVM无法处理或恢复的严重问题

  • 比如stack满了,compile一般检查不到,一般与“无限递归忘记写终止条件”或者“设置了一堆超大局部变量”或者“写了一大堆method互相调用”把stack空间占满了
  • 虚拟机运行错误 Virtual MachineError 比如当JVM不再有继续执行操作所需的内存资源,会报错OutOfMemoryError。
  • JVM运行时报错,比如 定义错误NoClassDefFoundError,链接错误LinkageError

如上图,Exception class一般还能救,一般都是程序员自己的锅:
Exception下分为unchecked exceptions 和 checked exception。

非检查异常unchecked exceptions:在compile阶段不需要catch或声明。并且是RuntimeException(运行时异常类)或它的子类,详细列出如下

  • RuntimeException(运行时异常)
    • ArrayIndexOutOfBoundsException数组下标越界
    • NullPointerException空指针异常
    • ArithmeticException算术异常
    • MissingResourceException丢失资源
    • ClassNotFoundException找不到类
    • 等等

检查异常checked exception :这类异常必须在方法签名中使用throws关键字声明,或者在方法体内部使用try-catch块进行处理。这意味着编译器要求这些method要么有程序块处理这些异常(使用try-catch块),要么在方法签名中使用throws关键字声明它们(等着这个class的父类try-catch)。比如程序想开文件 文件找不到了。检查异常类一般是指Exception下的IOException类或其子类。

Exception class存在的意义----让系统跑程序时候别崩溃,抛出一下这有个XXException,JVM不崩溃。

异常处理机制:抛出异常+捕获异常
五个关键字
try catch finally throw throws(注意throw和throws完全不一样)

try-catch

try-catch一般是成对使用。try块用于包含可能会抛出异常的代码。当try块中的代码抛出异常时,控制流将立即转移到与之匹配的catch块。catch块用于捕获并处理特定类型的异常。你可以有多个catch块来处理不同类型的异常。

在非常个别情况下,也有try-finally模块一起用,一般是文件调用,网络连接,数据库连接的method结束时被释放的情况下。

比如下面的例子,
try块内int r= m/n;是可能会抛出异常的代码,当异常被捕捉到,立刻转到catch块,如果直接碰到throw语句,那么后续代码就不看了,因为因为throw语句会立即结束当前方法的执行并将异常传递给调用者。如果throw旁边还有代码(包括System.out.println这种语句),建议写在catch块内throw关键字前面。
try块内可以写多个可能会抛出异常的代码,但一次只会触发一个,触发了一个就直接走catch模块了。

catch模块可以存在多个,是按顺序catch的,不要把大的父类放在第一个catch,那样后面的catch模组都不触发了。

package exception.demo02;public class mytest {public static void main(String[] args) {int m = 10;int n = 0;try {int r= m/n;} catch (ArrayIndexOutOfBoundsException e) {System.out.println("发现ArrayIndexOutOfBounds报错");}catch (ArithmeticException e){System.out.println("发现Arithmetic报错");}catch (RuntimeException e){System.out.println("发现Runtime报错");}}
}

运行结果

发现Arithmetic报错

throw关键字

在Java中,throw是一个关键字,不是method。当你想在代码中抛出一个异常时,你使用throw关键字并跟随一个异常object。这个异常对象可以是Java标准库中的异常类的一个实例object,也可以是你自定义的异常类的一个实例object。
一旦异常被抛出,程序的正常执行流程将被中断,并且控制权将转移到最近的异常处理代码,通常是catch块。

简单而言 throw后面跟着一个object,是继承于系统(或者自定义)Throwable class的object(见上图分类),触发后立刻终止程序,跳到最近的(或父级们)能处理该异常的catch模块,直到被处理或程序中止。

比如这句throw e;用在catch模块里,直接throw了异常object e,那么运行后我们会直接获得系统默认输出的这类Exception提示信息。这个提示或许不够清晰明确,有时程序员会将throw e;换成类似这样写 throw new ArithmeticException("啊啊啊你为什么要除以零");,用来输出自己想要的Exception提示信息。

Exception in thread "main" java.lang.ArithmeticException: / by zeroat exception.demo02.mytest.main(mytest.java:8)

整体代码见下面的例子:

先用简单的throw e;

package exception.demo02;public class mytest {public static void main(String[] args) {int m = 10;int n = 0;try {int r= m/n;} catch (ArrayIndexOutOfBoundsException e) {System.out.println("发现ArrayIndexOutOfBounds报错"); throw e;}catch (ArithmeticException e){System.out.println("发现Arithmetic报错");throw e;}catch (RuntimeException e){System.out.println("发现Runtime报错");throw e;}}
}

运行结果

Exception in thread "main" java.lang.ArithmeticException: / by zeroat exception.demo02.mytest.main(mytest.java:8)
发现Arithmetic报错

再将throw后面换成新建object new Exception_class(“用户自定义提示信息”) ;


package exception.demo02;public class mytest {public static void main(String[] args) {int m = 10;int n = 0;try {int r= m/n;} catch (ArrayIndexOutOfBoundsException e) {System.out.println("发现ArrayIndexOutOfBounds报错"); throw new ArrayIndexOutOfBoundsException("数组下标啊大哥大姐");}catch (ArithmeticException e){System.out.println("发现Arithmetic报错");throw new ArithmeticException("你除数是零啊!牛逼");}catch (RuntimeException e){System.out.println("发现Runtime报错");throw new RuntimeException("我点炒蘑菇没让你从种蘑菇开始啊");}}
}

程序运行结果

发现Arithmetic报错
Exception in thread "main" java.lang.ArithmeticException: 你除数是零啊!牛逼at exception.demo02.mytest.main(mytest.java:10)Process finished with exit code 1

printStackTrace()

除了在catch模块里直接throw异常object e使用语句throw e;有时程序员也选择使用printStackTrace(); printStackTrace()是Java中的一个异常处理方法,用于在控制台或日志文件中打印异常的堆栈跟踪信息。通过调用printStackTrace()方法,可以将这些Exception信息打印到控制台中。

package exception.demo02;public class mytest {public static void main(String[] args) {int m = 10;int n = 0;try {my_div(m,n);}catch (ArrayIndexOutOfBoundsException e) {e.printStackTrace();}catch (ArithmeticException e){e.printStackTrace();}catch (RuntimeException e){e.printStackTrace();}}public static int my_div(int a, int b) throws ArithmeticException {return a/b;}
}

运行结果:

java.lang.ArithmeticException: / by zeroat exception.demo02.mytest.my_div(mytest.java:21)at exception.demo02.mytest.main(mytest.java:8)Process finished with exit code 0

throws

Java允许程序员在method的声明中使用throws关键字来声明可能会抛出的异常。throws的位置写在method名称那行的最后面+可能出现的Exception种类,可写多个exception种类,用逗号隔开),比如public void doSomething() throws IOException,RuntimeException,ArithmeticException

如果一个方法的声明中使用了throws关键字来声明可能会抛出的异常,那么调用这个方法的代码不一定需要使用try-catch块来捕获这个异常。有几种处理异常的方式:

  • 使用try-catch块:这是最常见的处理方式。调用者可以使用try-catch块来捕获并处理可能抛出的异常。
  • 使用finally块:finally块可以用于在try块之后执行一些清理代码,无论是否发生异常都会执行。但请注意,finally块不能用来处理异常,它仅仅是用来执行清理任务。

以下是伪处理方式:(实际没有真的处理异常,而是丢给了别人或者直接摆烂)

  • 继续向上抛出异常:如果调用者不想在当前方法中处理异常,它可以选择不捕获该异常,这样异常会继续向上抛出,直到被某个上层方法捕获或者最终由JVM处理(通常会导致程序终止)。
  • 声明方法也抛出异常:如果调用者是一个方法,并且它也不想处理异常,那么它可以在自己的方法签名中使用throws关键字来声明同样的异常。这样,异常会继续向上传递,直到最终有某个方法处理了它。
  • 忽略异常:在某些特殊情况下,调用者可能会选择忽略异常。这是一种非常不推荐的做法,因为它可能会隐藏问题,导致程序在后续执行中出现不可预测的行为。

下面这个例子中,my_div method声明了它可能会抛出ArithmeticException,RuntimeException,于是在main模块try-catch程序对这些exception统统进行了涵盖,完成了异常(们)的处理。

package exception.demo02;public class mytest {public static void main(String[] args) {int m = 10;int n = 0;try {my_div(m,n);}catch (ArrayIndexOutOfBoundsException e) {e.printStackTrace();}catch (ArithmeticException e){e.printStackTrace();}catch (RuntimeException e){e.printStackTrace();}}public static int my_div(int a, int b) throws ArithmeticException, RuntimeException{return a/b;}
}
java.lang.ArithmeticException: / by zeroat exception.demo02.mytest.my_div(mytest.java:21)at exception.demo02.mytest.main(mytest.java:8)Process finished with exit code 0

throws和throw关键字经常一起使用来处理异常,但它们也可以单独使用。可以只使用throws,表明方法不处理某些异常,让调用者去处理。也可以只使用throw,在方法内部遇到错误时直接抛出异常,并不在方法签名中声明任何异常。

下面这个例子,doSomething方法声明了它可能会抛出IOException,但方法内部没有使用throw关键字来实际抛出异常。调用这个方法的代码需要处理或继续传递这个异常。

public class Example {  public void doSomething() throws IOException {  // 这里可能会抛出IOException  FileInputStream fis = new FileInputStream("file.txt"); // ...  }  
}

如果声明了可能抛出的异常,但层层调用它时最终到了main都没人处理这个异常(没人用try-catch模块处理),编译器会报错。

public class mytest {  public static void main(String[] args) {  //下面这个try-catch模块要是不存在,直接调用mymethod(),绝对报错!try {  mymethod();  } catch (Exception e) {  e.printStackTrace();  }  }  public static void mymethod() throws Exception {  throw new Exception("An exception occurred");  }  }

特殊的情况是,如果method声明了可能抛出的异常,层层调用它时最终到了main没人用try-catch模块处理,都在一层一层throws向上抛,main也摆烂直接用了throws向上抛,这种编译器不会报错。而是会在编译器输出Exception的具体内容。

下面这个例子就相当于层层向上抛,最后main也抛,编译器是不会报错的。

public class mytest {  public static void main(String[] args) throws Exception {  mymethod();  }  public static void mymethod() throws Exception {  throw new Exception("An exception occurred");  }  }

知识补充

快速生成try catch finally结构块:

IDEA有一个功能可以快速生成try catch finally结构块,这个功能叫做Surround with,快捷键是ctrl+alt+t
由于它和ubuntu open terminal重复了,我们可以用下面的方法,将快捷键更改,改为alt+c,下次使用时,将待检验模块高亮,然后alt+c,在里面选择 try catch finally即可。

Tips: IntelliJ IDEA 中如何更改快捷键设置?

 - 打开 IntelliJ IDEA,在顶部菜单栏选择 "File",然后在下拉菜单中选择 "Settings"(对于 macOS 用户,选择 "IntelliJ IDEA" -> "Preferences")。- 在弹出的 "Settings" 对话框中,在左侧的导航栏选择 "Keymap"。-  在 "Keymap" 界面,你可以看到所有的快捷键设置。你可以通过搜索功能找到你想要更改的特定快捷键。在搜索框中输入你想要更改的功能名称,然后在下方的列表中找到它。- 找到你想要更改的快捷键后,右键点击它,然后在弹出的菜单中选择 "Remove" 来删除原有的快捷键。- 接着,右键点击你刚刚删除快捷键的功能,然后在弹出的菜单中选择 "Add Keyboard Shortcut"。- 在弹出的 "Enter Keyboard Shortcut" 对话框中,按下你想要设置的新快捷键,然后点击 "OK"。- 最后,点击 "Apply" 按钮应用更改,然后点击 "OK" 按钮关闭 "Settings" 对话框。

throw和throws关键字的用法:

助记
主动throw exception object inside method block using throw
主动throws (potential) exception class on method title using throws

举例,分母参数为零的情况下,将算式写完,用alt+c快捷键打开surround with选择try catch finally快速生成exception抛出模块

package exception;public class test2 {public static void main(String[] args) {int a = 5;int b = 0;int c = 7;try {System.out.println(a+c/b);} catch (Exception e) {//e.printStackTrace();//做法1:打印错误的stack信息//System.exit(0); //做法2:直接退出 里面的参数可以写0或者1throw new RuntimeException(e); //做法3:直接抛出错误} finally {}}
}

运行结果

Exception in thread "main" java.lang.RuntimeException: java.lang.ArithmeticException: / by zeroat exception.test2.main(test2.java:13)
Caused by: java.lang.ArithmeticException: / by zeroat exception.test2.main(test2.java:9)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/691305.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

洛谷C++简单题小练习day15—计算阶乘小程序(不用循环)

day15--计算阶乘小程序--2.19 习题概述 题目描述 求 n!,也就是 123⋯n。 挑战:尝试不使用循环语句(for、while)完成这个任务。 输入格式 第一行输入一个正整数 n。 输出格式 输出一个正整数,表示 n! 代码部分 …

瑞芯微RK3588驱动配置之DVP摄像头1

发现很多人不会RK3588DVP摄像头的驱动配置,这里简单分享一下,各位老铁点个赞,一键三连,给点动力。 这篇主要讲一下DTS设备树的配置,下篇写具体的驱动设计。 因为瑞芯微的大部分芯片都支持DVP摄像头,配置都大…

Android内存分析

1.分析某个进程的内存情况 1.1 生成.hprof文件 可以在运行的设备上,使用adb命令生成 .hprof文件,表示在执行命令的那一刻,该进程的内存情况。如下: am dumpheap com.example.demo /data/local/tmp/demo.hprof这里就是对包名为c…

【力扣白嫖日记】1890.2020年最后一次登录

前言 练习sql语句,所有题目来自于力扣(https://leetcode.cn/problemset/database/)的免费数据库练习题。 今日题目: 1890.2020年最后一次登录 表:Logins 列名类型user_idinttime_stampvarchar (user_id, time_sta…

Unity UGUI的DrawCall优化

Unity UGUI是一种强大的用户界面设计工具,它可以帮助开发者快速创建各种界面元素,从按钮和文本到滑块和面板等。然而,在使用UGUI时,一个常见的性能瓶颈就是DrawCall过多导致的性能下降。在本文中,我们将深入探讨UGUI的…

搜索算法(算法竞赛、蓝桥杯)--BFS八数码难题、抓住那头牛、魔板问题

1、B站视频链接&#xff1a;B14 BFS 八数码难题_哔哩哔哩_bilibili 题目链接&#xff1a;八数码难题 - 洛谷 #include <bits/stdc.h> using namespace std; char c; string str; unordered_map<string,int> d;//记录步数 queue<string> q; int dx[4]{-1,0,1…

微服务—RabbitMQ高级(业务在各方面的可靠性)

本博客为个人学习笔记&#xff0c;学习网站&#xff1a;2023黑马程序员RabbitMQ入门到实战教程 高级篇章节 目录 生产者可靠性 生产者重连机制 生产者确认机制 介绍 实现 总结与建议 MQ可靠性 数据持久化 LazyQueue 消费者可靠性 消费者确认机制 失败重试机制 失…

深度学习之pytorch实现逻辑斯蒂回归

深度学习之pytorch实现逻辑斯蒂回归 解决的问题数学公式logiatic函数损失值 代码与线性回归代码的区别数据损失值构造回归的函数 结果分析 解决的问题 logistic 适用于分类问题&#xff0c;这里案例( y为0和1 &#xff0c;0和 1 分别代表一类&#xff09; 于解决二分类&#xf…

2024上海国际地下空间工程与技术展览会

2024上海国际地下空间工程与技术展览会 Underground Space Project and Technology Exhibition 2024 2024年10月31日-11月2日 上海世博展览馆 国展路1099号 展会规模&#xff1a;25000平方米 主办单位&#xff1a;联合国人居署 上海市住房与城乡建设管理委员会 一、城博会…

农村分散式污废水处理需要哪些设备

农村地区由于存在分散式的生活污废水&#xff0c;需要通过适合的设备进行处理和处理。在农村分散式污废水处理中&#xff0c;有几种主要的设备是必不可少的&#xff1a; 1. 废水收集器&#xff1a;废水收集器用于将分散式废水收集起来&#xff0c;确保其能够被有效地输送至处理…

高压圆盘电阻器----氧化锌电阻(1)?

特点 1&#xff09;100%陶瓷固体压铸结构&#xff0c;主要由氧化锌、氧化铝、氧化镁和人造粘土组成 2&#xff09;承受高脉冲能量&#xff0c;适用于超高压环境&#xff0c;可用于1000kV以上电路&#xff0c;瞬时功率可达3kkw 3&#xff09;无感设计&#xff0c;非传统绕线&…

【ArcGIS Pro二次开发】(82):玩个花活_控规指标块生成

一、要实现的效果 废话不多说&#xff0c;这次要实现的是类似控规指标块的标注&#xff1a; 这里只是示例&#xff0c;用了5个格子&#xff0c;做成9个格子也是可以的。 实现这个效果最关键的是要用到Pro中的复合标注。 关于复合标注的用法可以搜一下帮助里的【使用复合注释…

基于WOA优化的Bi-LSTM多输入回归预测(Matlab)鲸鱼算法优化双向长短期神经网络回归预测

目录 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 亮点与优势&#xff1a; 二、实际运行效果&#xff1a; 三、算法介绍&#xff1a; 鲸鱼优化算法&#xff08;WOA&#xff09;&#xff1a; 双向长短期神经网络&#xff08;Bi-LSTM&#xff09;&#xff1a…

raspi_os 32-bit lite下使用摄像头

前置条件&#xff1a;已经烧录32位版本的raspi os 按照如下步骤即可使用摄像头&#xff1a; 将SD卡放入读卡器插到电脑上根目录下打开config.txtctrl f 查找到camera_auto_detect1将其注释定位到文件末尾添加如下 gpu_mem128 start_x1将SD卡放回树莓派启动&#xff0c;键入…

VMware下安装银河麒麟V10操作系统

VMware下安装银河麒麟V10操作系统 文章目录 下载在VMware中应用编辑虚拟机设置 在麒麟系统内安装 下载 官网下载&#xff1a;https://www.kylinos.cn/ 银河麒麟、中标麒麟、开放麒麟、星光麒麟 在VMware中应用 1.新建虚拟机 2.稍后安装操作系统 3.新建虚拟机向导&#xff0…

【无标题】力扣报错:member access within null pointer of type ‘struct ListNode‘

项目场景&#xff1a; 做单链表反转题目&#xff0c;报错&#xff1a;member access within null pointer of type ‘struct ListNode’ 题目链接:LINK 问题描述 我明明在初始化指针时候&#xff0c;已经处理了n2->next情况却依然报错 这个报错提示含义是&#xff1a;大概就…

Photoshop 2023(Ps)下载安装及详细安装教程

Photoshop(Ps)的介绍 Adobe Photoshop&#xff0c;简称“PS”&#xff0c;是由AdobeSystems开发和发行的图像处理软件。Photoshop主要处理以像素所构成的数字图像。使用其众多的编修与绘图工具&#xff0c;可以有效地进行图片编辑和创造工作。PS有很多功能&#xff0c;在图像、…

拼夕夕 拼多多关键词恢复供应,欢迎骚扰

API接口&#xff08;Application Programming Interface&#xff09;是一种定义了软件组件之间交互的规范。它允许不同的软件系统之间进行通信和数据交换&#xff0c;使得开发者可以利用已有的功能和服务来构建自己的应用程序。 API接口可以分为不同的类型&#xff0c;包括Web …

【LeetCode: 590. N 叉树的后序遍历 + DFS】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

C#使用 AutoUpdater.NET 实现程序自动更新

写在前面 开发桌面应用程序的时候&#xff0c;经常会因为新增功能需求或修复已知问题&#xff0c;要求客户更新应用程序&#xff0c;为了更好的服务客户&#xff0c;通常会在程序启动时判断版本变更情况&#xff0c;如发现新版本则自动弹出更新对话框&#xff0c;提醒客户更新…