JAVA学习*异常

什么是异常

在 Java 里,异常是指程序运行期间出现的不正常状况,它会中断程序的正常执行流程。

异常的分类

Java 中的异常是对象,这些对象都继承自 Throwable类。Throwable类有两个主要的子类:Error 和 Exception。
Error类表示严重的系统级错误。
Exception类代表程序中可以被捕获和处理的异常情况。Exception类又分为两类:受查异常(编译时异常)和运行时异常。
在这里插入图片描述

异常的处理

对于异常的处理有5个关键字:try catch finally throw throws

throw关键字

用于在方法内部抛出异常。

throw new XXXXException("产生异常的原因");

代码展示:

public static void func(int a) throws ArithmeticException{if(a == 0) {throw new ArithmeticException("除数为零,算数异常");}int b = 40 / a;System.out.println(b);int[] array = null;if(array == null) {throw new NullPointerException("空指针异常");}System.out.println(array[1]);
}
public static void main(String[] args) {int a = 0;func(a);
}

在这里插入图片描述

代码解释:

1、为什么要抛出异常?是为了将错误信息告知程序员。
2、throw用于抛出异常,必须在方法内部使用。
3、用throw只是单纯抛出问题,并没有解决异常。对于抛出的是RunTimeException 或者 RunTimeException 的子类是,则可以不用处理,直接交给JVM处理。
4、异常一旦抛出后面的代码将不再执行。像上述代码就不会输出b的值,也不会爆出空指针异常。
当我们将a == 2时,输出b的值,爆出空指针异常。**也就是说同一时刻只能抛出一个异常!**不会同时抛出多个异常。
在这里插入图片描述
5、对于抛出编译时异常,需要用throws在方法声明中声明可能抛出的异常。

throws关键字

用于在方法声明中声明可能抛出的异常。

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

代码展示:

1、对于刚才的代码,我们也可以声明可能发生的异常。

public static void func(int a) throws ArithmeticException,NullPointerException{if(a == 0) {throw new ArithmeticException("除数为零,算数异常");}int b = 40 / a;System.out.println(b);int[] array = null;if(array == null) {throw new NullPointerException("空指针异常");}System.out.println(array[1]);
}
public static void main(String[] args) {int a = 2;func(a);
}

2、在学习Cloneable接口时,有出现throws关键字。

class Student implements Cloneable{@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}
public class Test2 {public static void main(String[] args) throws CloneNotSupportedException{Student student = new Student();Student student1 = (Student) student.clone();}
}

代码解释:

1、throws告诉调用者这个方法可能存会抛出异常,调用者需要处理这个异常。使用throws实际上是将处理代码的责任转移给了调用改方法的代码。

像上述代码:重写的clone()方法声明了CloneNotSupportedException异常。当main方法调用了clone()方法,需要去处理这个异常。但是,main方法也声明了CloneNotSupportedException异常,此时将由JVM去处理。

2、throws必须跟在方法的参数列表之后。
3、如果抛出的多个异常存在父子关系,可以声明父类。

try和catch关键字

try是用于包含可能会抛出异常的代码块。
catch是用于捕获并处理try块中抛出的异常。

try {可能会抛出异常的代码块
} catch (异常1 e) {throw new RuntimeException(e);
} catch (异常2 e) {throw new RuntimeException(e);
}

代码展示:

代码案例1:

public static void func(int a) {int b = 40 / a;System.out.println(b);int[] array = null;System.out.println(array[1]);
}
public static void main(String[] args) {int a = 0;try {func(a);System.out.println("try内部的代码被执行了");} catch (ArithmeticException e) {e.printStackTrace();System.out.println("捕捉到算数异常");} catch (NullPointerException e) {e.printStackTrace();System.out.println("捕捉到空指针异常");}System.out.println("try-catch后面的代码被执行了");
}

输出:
在这里插入图片描述

代码案例2:

public static void func(int a) {int b = 40 / a;System.out.println(b);int[] array = null;System.out.println(array[1]);
}
public static void main(String[] args) {int a = 0;try {func(a);System.out.println("try内部的代码被执行了");} catch (IndexOutOfBoundsException e) {e.printStackTrace();System.out.println("捕捉到下标越界异常");} catch (NullPointerException e) {e.printStackTrace();System.out.println("捕捉到空指针异常");}System.out.println("try-catch后面的代码被执行了");
}

输出:
在这里插入图片描述
代码案例3:

class Student implements Cloneable {public int age;public String name;@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}
public class Test {public static void main(String[] args) throws CloneNotSupportedException{Student student = new Student();Student student1 = (Student) student.clone();}
}
public class Test {public static void main(String[] args) {try {test1();} catch (CloneNotSupportedException e) {e.printStackTrace();}}public static void test1() throws CloneNotSupportedException{throw new CloneNotSupportedException();}
}
public class Test {public static void main(String[] args) {test1();}public static void test1() {try {throw new CloneNotSupportedException();} catch (CloneNotSupportedException e) {e.printStackTrace();}}
}

代码解释:

1、 try内不是一定要有异常的。
2、 在代码案例1中:我们发现func(a);后面的代码没有被执行。说明在捕获到了异常后,try包裹的后面的代码就不会被执行(这是为了考虑到安全性)。会执行捕获到的catch中的代码(案例中也就是e.printStackTrace();System.out.println("捕捉到算数异常");)。当捕获到异常后,try-catch后面的代码仍会被执行。
3、 在代码案例1中:我们发现当存在多个异常时,只会捕捉一个异常,这个异常是,try中最先发生的异常在catch中匹配成功的第一个异常(注意:并不是第一catch的异常)。(当然,前提是抛出的异常类型和catch中的异常匹配的时候)
4、 在代码案例2中:我们发现当抛出的异常类型和catch中的异常不匹配时,抛出的异常不会被处理,此时就会交给JVM处理,JVM处理就会终止程序,输出异常信息,将不会再执行后面语句了。
5、 在代码案例3中:对于编译时异常我们可以将不断抛出,最终交给JVM处理;

就是第一个代码,我们再学习接口的时候就有见过。由于重写的clone方法声明了CloneNotSupportedException异常,此时我们需要去对这个异常进行处理,当时我们选择的是对异常进行抛出给调用者(main方法),main方法继续抛出给JVM处理。

也可以自己使用try-catch进行处理。

第二个和第三个代码都使用了try-catch来处理异常,只是在处理异常的地方不一样,本质上是一样的。

6、 由于异常之间是存在继承关系的,在根据第3点知识,我们可以知道catch中的第一个异常不能是Exception!因为Exception是所有异常的父类。catch(Exception e){}虽然不能放在第一个,但是可以放在最后一个,进行一个兜底的作用。防止有些异常没有被我们捕捉到。也是就是如果异常之间具有父子关系,一定是子类异常在前catch,父类异常在后catch,否则语法错误!
7、 当要捕捉的异常较多的时候,可以catch合并起来写。

catch(ArithmeticException | NullPointerException e) {}

但不推荐这么写,会造成分不清具体发生的是什么异常。当然也不允许只写个Exception。

finally关键字

finally关键字通常和try-catch语句搭配使用。

作用:

finally块常用于确保资源(如文件、网络连接、数据库连接等)被正确关闭,避免资源泄漏。

代码案例:

代码案例1:

public class Test2 {public static void main(String[] args) {try {int result = 10 / 0; // 这里会抛出ArithmeticException异常System.out.println("结果: " + result);} catch (ArithmeticException e) {e.printStackTrace();System.out.println("捕获到算数异常");} finally {System.out.println("finally块中的代码一定会被执行");}}
}

在这里插入图片描述
代码案例2:

import java.util.InputMismatchException;
import java.util.Scanner;public class TestFinally {public static int getNum() {Scanner scanner = null;try {scanner = new Scanner(System.in);int data = scanner.nextInt();return data;} catch (InputMismatchException e) {e.printStackTrace();} finally {System.out.println("finally内代码被执行了");}System.out.println("finally后面代码被执行了");if(scanner != null) {scanner.close();}return 0;}public static void main(String[] args) {int data = getNum();System.out.println(data);}
}

在 Java 里,InputMismatchException是RuntimeException的子类。当程序借助Scanner类从输入源(像键盘、文件等)读取数据,而输入的数据类型和程序所期望的数据类型不相符时,就会抛出此异常。

当输入数字时:
在这里插入图片描述
当输入的不是数字时:
在这里插入图片描述

代码案例3:

public class Test3 {public static void main(String[] args) {int test = test();System.out.println(test);}public static int test() {int a = 0;try {int b = 40/a;return 1;} catch (ArithmeticException e) {return 0;} finally {return -1;}}
}

输出:-1

代码解释:

1、 在代码案例1中:无论try块里的代码是否抛出异常,finally块中的代码都会被执行。
2、 在代码案例2中:
当输入数字时,并没有产生异常,所以遇到了try中的return,返回输入的数字。但代码并没有走关闭Scanner的代码,导致资源泄露。(但finally中的代码一定会被执行。)
当输入非数字时,产生异常,此时异常被捕获,try中的return语句就不会被执行。走完catch和finally后,会进入if语句,返回0。
3、 在代码案例3中:当try和finally中都有return语句,此时一定会执行finally中的return语句。(一定要记住:finally中的代码是一定会被执行的!)
4、 对于快速使用try-catch-finally的快捷键:选中代码块,ctrl + Alt + t
在这里插入图片描述

异常处理流程总结

1、 对于运行时异常,可以使用try-catch-finally;也可以使用if语句进行判断,其中使用throw手动抛出异常。对于使用throws来说,只是起到了一个声明存在可能发生的异常,可以用可以不用。
2、 对于编译时异常,可以使用try-catch-finally;也可以使用throws交给调用者处理,最终会交给JVM处理。

1、程序执行try中的代码
2、当try中没有发生异常,程序就会正常执行;当发生异常,就会看和catch中的异常是否匹配。
3、匹配成功,执行当中catch的语句;否则交给调用者处理,当调用者始终没有真正处理,就会交给JVM处理,此时程序就会终止。
4、finally中的代码始终被执行!

自定义异常

代码案例:

public class LogIn {private String username = "admin";private String password = "123";public LogIn(String username, String passeword) {this.username = username;this.password = passeword;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public LogIn() {}public void login() throws PasswordException {if (!this.username.equals("admin")) {throw new UsernameException("用户名错误或不存在");}if (!this.password.equals("123")) {throw new PasswordException("密码错误");}System.out.println("登录成功!");}
}
public class UsernameException extends RuntimeException{public UsernameException(String message) {super(message);}public UsernameException() {super();}
}
public class PasswordException extends Exception{public PasswordException() {super();}public PasswordException(String message) {super(message);}
}
import java.util.Scanner;public class CustomExceptionTest {public static void main(String[] args) {Scanner scanner = null;int count = 3;scanner = new Scanner(System.in);do {LogIn logIn = new LogIn();System.out.println("请输入用户名:");logIn.setUsername(scanner.nextLine());System.out.println("请输入密码:");logIn.setPassword(scanner.nextLine());try {logIn.login();} catch (UsernameException e) {e.printStackTrace();} catch (PasswordException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();} finally {if(scanner != null && count == 0) {scanner.close();}count--;if(count != 0) {System.out.println("你还有" + count + "次机会!");}else if(count == 0) {System.out.println("请1分钟后在试");}}} while (count != 0);}
}

代码解释:

1、对于自定义异常,需要继承异常类。一般是Exception或者RuntimeException。
2、继承Exception默认被定义为受查异常。继承RuntimeException默认被定义为运行时异常。
3、对于自定义异常可以重写构造方法。

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

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

相关文章

DataGear 5.3.0 制作支持导出表格数据的数据可视化看板

DataGear 内置表格图表底层采用的是DataTable表格组件,默认并未引入导出数据的JS支持库,如果有导出表格数据需求,则可以在看板中引入导出相关JS支持库,制作具有导出CSV、Excel、PDF功能的表格数据看板。 在新发布的5.3.0版本中&a…

【电气设计】接地/浮地设计

在工作的过程中,遇到了需要测量接地阻抗的情况,组内讨论提到了保护接地和功能接地的相关需求。此文章用来记录这个过程的学习和感悟。 人体触电的原理: 可以看到我们形成了电流回路,导致触电。因此我们需要针对设备做一些保护设计…

【计算机操作系统】线程的概念和特点

1、什么是线程,为什么要引入线程? 还没引入进程之前,系统中各个程序只能串行执行。 比如:当我们在使用QQ与好友视频时,我们可以给其他好友发信息,发送文件...,我们知道进程是程序的一次执行&am…

【C++数据库】SQLite3数据库连接与操作

注意:本文代码均为C++20标准下实现 一、SQLite3库安装 1.1 安装库文件 【工具】跨平台C++包管理利器vcpkg完全指南 vcpkg install sqlite3# 集成至系统目录,之前执行过此命令的无需再次执行 vcpkg integrate install1.2 验证代码 在VS2022中新建控制台项目,测试代码如下…

CLion下载安装(Windows11)

目录 CLion工具下载安装其他 CLion CLion-2024.1.4.exe 工具 系统:Windows 11 下载 1.通过百度网盘分享的文件:CLion-2024.1.4.exe 链接:https://pan.baidu.com/s/1-zH0rZPCZtQ60IqdHA7Cew?pwdux5a 提取码:ux5a 安装 打开…

‘无法定位程序输入点kernel32.dll’详细的修复方法,一键快速修复kernel32.dll

在 Windows 系统运行过程中,若程序提示“无法定位程序输入点 kernel32.dll”,往往意味着程序调用了 kernel32.dll 中不存在或已变更的函数接口。作为系统的核心动态链接库,kernel32.dll 承担着内存管理、进程控制、文件操作等底层功能&#x…

二层综合实验

拓扑图 实验要求 1.内网IP地址使用172.16.6.0/16分配 2.sw1和sW2之间互为备份 3.VRRP/STP/VLAN/Eth-trunk均使用 4.所有Pc均通过DHCP获取IP地址 5.ISP只能配置IP地址 6.所有电脑可以正常访问IsP路由器环回 实验思路 这是一个二层综合实验每当拿到一个实验看清楚要求之后都有…

PS 切割图片

选择矩形工具绘制矩形 选中全部矩形,旋转一下角度 鼠标选中最下面的黄色图片,按住 Ctrl 键, 再用鼠标点击矩形的缩略图,选中选区,再按下 ctrlj ,复制选区。 同样操作弄好其他的矩形选区,再删除…

项目管理证书 PMP 的含金量高吗?

一、国内PMP的含金量 1. 行业认可度 高需求行业:IT、通信、建筑、制造、金融等行业对PMP认可度较高,尤其是跨国企业、大型国企(如华为、阿里、腾讯、中建等)常将PMP作为项目经理岗位的优先录用条件。 招聘门槛:部分企…

旅游CMS选型:WordPress、Joomla与Drupal对比

内容概要 在旅游行业数字化转型进程中,内容管理系统(CMS)的选择直接影响网站运营效率与用户体验。WordPress、Joomla和Drupal作为全球主流的开源CMS平台,其功能特性与行业适配性存在显著差异。本文将从旅游企业核心需求出发&…

LeetCode349两个数组的交集

思路: 这个题目是查找交集,考虑用哈希数组,c语言用数组建立哈希表来解题,题目限定了数组长度在1000以内,那么可以设定一个result数组用于存储交集 1.我们需要将nums1映射到哈希表中 2.遍历nums2查询哈希表中是否存在该…

安装教程:windows上安装oracle详细教程

文章目录 前言一、下载 Oracle 安装包二、安装步骤三、连接ORACLE可视化工具1.1 PL/SQL Developer1.2 navicat 结束语优质源码分享 windows上安装oracle详细教程,在Windows上安装Oracle数据库需遵循以下步骤:首先,从官网下载对应版本的Oracle…

4、网工软考—VLAN配置—hybird配置

1、实验环境搭建: 2、实验过程 SW1: 先创建vlan2和vlan3 [Huawei-Ethernet0/0/2]port link-type hybrid //hybird端口 [Huawei-Ethernet0/0/2]port hybrid pvid vlan 2 [Huawei-Ethernet0/0/2]port hybrid untagged vlan 10 //撕掉vlan10的标签 …

平台清洗行动:AI浏览器用户生存率高出传统方案17倍

平台清洗行动:AI 浏览器用户生存率高出传统方案 17 倍 在这个数字化时代,网络环境的复杂性不断增加,用户在浏览网页时面临着各种风险,包括恶意软件、钓鱼攻击和隐私泄露等。为了应对这些挑战,AI 浏览器应运而生&#…

【C++篇】C++入门基础(一)

💬 欢迎讨论:在阅读过程中有任何疑问,欢迎在评论区留言,我们一起交流学习! 👍 点赞、收藏与分享:如果你觉得这篇文章对你有帮助,记得点赞、收藏,并分享给更多对C感兴趣的…

MaskFormer语义分割算法测试

MaskFormer是一套基于transformer结构的语义分割代码。 链接地址: https://github.com/facebookresearch/MaskFormer/tree/main 测试用的数据集:ADE20k Dataset MIT Scene Parsing Benchmark 该数据集可通过上述链接下载,其中training含有…

javaWeb vue的简单语法

一、简介 两大核心优势: 声明式渲染:Vue 基于标准 HTML 拓展了一套模板语法,使得我们可以声明式地描述最终输出的 HTML 和 JavaScript 状态之间的关系。 响应性:Vue 会自动跟踪 JavaScript 状态并在其发生变化时响应式地更新 D…

vue create创建 Vue-router 工程

vue create创建 Vue-router 工程 参考 创建vue项目的两种方式:vue-create与vite https://www.cnblogs.com/reverse-x/p/16806534.html Vue2 脚手架 创建工程 测试程序 https://blog.csdn.net/wowocpp/article/details/146590400 在 上面的基础上 cd .\vue2-demo\…

CXL UIO Direct P2P学习

前言: 在CXL协议中,UIO(Unordered Input/Output) 是一种支持设备间直接通信(Peer-to-Peer, P2P)的机制,旨在绕过主机CPU或内存的干预,降低延迟并提升效率。以下是UIO的核心概念及UI…

口腔种植全流程AI导航系统及辅助诊疗与耗材智能化编程分析

一、系统架构与编程框架设计 口腔种植全流程人工智能导航系统的开发是一项高度复杂的多学科融合工程,其核心架构需在医学精准性、工程实时性与临床实用性之间实现平衡。系统设计以模块化分层架构为基础,结合高实时性数据流与多模态协同控制理念,覆盖从数据采集、智能决策到…