零基础学Java第二十二讲---异常(2)

        续接上一讲

目录

一、异常的处理(续)

1、异常的捕获-try-catch捕获并处理异常

1.1关于异常的处理方式

2、finally

3、异常的处理流程

二、自定义异常类

1、实现自定义异常类


一、异常的处理(续)

1、异常的捕获-try-catch捕获并处理异常

        throws对异常并没有真正处理,而是将异常报告给抛出异常方法的调用者,由调用者处理。如果真正要对异常进行处理,就需要try-catch。

语法格式:
try{// 将可能出现异常的代码放在这⾥ 
}catch(要捕获的异常类型e){// 如果try中的代码抛出异常了,此处catch捕获时异常类型与try中抛出的异常类型⼀致时,或者是try中抛出异常的基类时,就会被捕获到 // 对异常就可以正常处理,处理完成后,跳出try-catch结构,继续执⾏后序代码 
}[catch(异常类型 e){// 对异常进⾏处理 
}finally{// 此处代码⼀定会被执⾏到 
}]// 后序代码
// 当异常被捕获到时,异常就被处理了,这⾥的后序代码⼀定会执⾏ 
// 如果捕获了,由于捕获时类型不对,那就没有捕获到,这⾥的代码就不会被执⾏注意:
1. []中表⽰可选项,可以添加,也可以不⽤添加
2. try中的代码可能会抛出异常,也可能不会

例:读取配置文件,如果配置文件名字不是指定名字,抛出异常,调用者进行异常处理

 public class Config {File file;public void openConfig(String filename) throws FileNotFoundException{if(!filename.equals("config.ini")){throw new FileNotFoundException("配置⽂件名字不对");}// 打开⽂件 }public void readConfig(){}public static void main(String[] args) {Config config = new Config();try {config.openConfig("config.txt");System.out.println("⽂件打开成功");} catch (IOException e) {// 异常的处理⽅式//System.out.println(e.getMessage());   // 只打印异常信息 //System.out.println(e);                // 打印异常类型:异常信息             e.printStackTrace();                    // 打印信息最全⾯}// ⼀旦异常被捕获处理了,此处的代码会执⾏ System.out.println("异常如果被处理了,这⾥的代码也可以执⾏");}}

1.1关于异常的处理方式

异常的种类有很多,我们要根据不同的业务场景来决定:

(1)对于比较严重的问题(如算钱),应该直接让程序崩溃,减小损失

(2)对于不太严重的问题,可以记录错误日志,通过监控报警程序及时通知告知程序猿

(3)对于可能会恢复的问题(网络相关场景),可以尝试重试

        在我们当前的代码中采取的是经过简化的第⼆种方式.我们记录的错误日志是出现异常的方法调用信息,能很快速的让我们找到出现异常的位置.以后在实际工作中我们会采取更完备的方式来记录异常信息

#注:

(1)try块内抛出异常位置之后的代码将不会被执行

(2)如果抛出异常类型与catch时异常类型不匹配,即异常不会被成功捕获,也就不会被处理,继续往外抛,直到JVM收到后中断程序----异常是按照类型来捕获的

 public static void main(String[] args) {try {int[] array = {1,2,3};System.out.println(array[3]);  // 此处会抛出数组越界异常 }catch (NullPointerException e){   // 捕获时候捕获的是空指针异常--真正的异常⽆法被捕获到 e.printStackTrace();}System.out.println("后续代码");}Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3at day20210917.ArrayOperator.main(ArrayOperator.java:24)

(3)try中可能会抛出多个不同的异常对象,则必须用多个catch来捕获----即多种异常,多次捕获

 public static void main(String[] args) {int[] array = {1, 2, 3};try {System.out.println("before");// array  = null;System.out.println(array [100]);System.out.println("after");} catch (ArrayIndexOutOfBoundsException e) {System.out.println("这是个数组下标越界异常");e.printStackTrace();} catch (NullPointerException e) {System.out.println("这是个空指针异常");e.printStackTrace();}System.out.println("after try catch");}

        如果多个异常完全相同,也可以这样写:

 catch (ArrayIndexOutOfBoundsException | NullPointerException e) {...}

        如果异常之间具有父子关系,⼀定是子类异常在前catch,父类异常在后catch,否则语法错误:

 public static void main(String[] args) {int[] arr = {1, 2, 3};try {System.out.println("before");arr = null;System.out.println(arr[100]);System.out.println("after");} catch (Exception e) {   // Exception可以捕获到所有异常 e.printStackTrace();}catch (NullPointerException e){  // 永远都捕获执⾏到 e.printStackTrace();}System.out.println("after try catch");}Error:(33, 10) java: 已捕获到异常错误java.lang.NullPointerException

(4)可以通过⼀个catch捕获所有的异常,即多个异常,⼀次捕获(不推荐)

 public static void main(String[] args) {int[] arr = {1, 2, 3};try {System.out.println("before");arr = null;System.out.println(arr[100]);System.out.println("after");} catch (Exception e) {e.printStackTrace();}System.out.println("after try catch");}

        由于Exception类是所有异常类的父类.因此可以用这个类型表示捕捉所有异常.

#注:catch进行类型匹配的时候,不光会匹配相同类型的异常对象,也会捕捉目标异常类型的子类对 象

2、finally

        在写程序时,有些特定的代码,不论程序是否发⽣异常,都需要执行,比如程序中打开的资源:网络连接、数据库连接、IO流等,在程序正常或者异常退出时,必须要对资源进进行回收。另外,因为异常会引发程序的跳转,可能导致有些语句执行不到,finally就是用来解决这个问题的。

语法格式:
try{// 可能会发⽣异常的代码 
}catch(异常类型 e){// 对捕获到的异常进⾏处理 
}finally{// 此处的语句⽆论是否发⽣异常,都会被执⾏到
}// 如果没有抛出异常,或者异常被捕获处理了,这⾥的代码也会执⾏
public static void main(String[] args) {try{int[] array = {1,2,3};array [100] = 10;array [0] = 10;}catch (ArrayIndexOutOfBoundsException e){System.out.println(e);}finally {System.out.println("finally中的代码⼀定会执⾏");}System.out.println("如果没有抛出异常,或者异常被处理了,try-catch后的代码也会执⾏");}

#注:finally中的代码⼀定会执行的,⼀般在finally中进行⼀些资源清理的扫尾工作,如果异常被捕获,那么将不会继续执行后续的内容,而是直接走完当前捕获异常的catch后直接走finally(除了finally其他的都不执行)

        finally 执行的时机是在方法返回之前(try或者catch中如果有return会在这个return之前执行 finally). 但是如果finally 中也存在return语句,那么就会执行finally中的return,从而不会执行到try 中原有的return.

        ⼀般我们不建议在finally中写return(会被编译器当做⼀个警告)

3、异常的处理流程

关于“调用栈”:

        方法之间是存在相互调用关系的,这种调用关系我们可以"调用栈"来描述.在JVM中有⼀块内存空间称为"虚拟机栈",专门存储方法之间的调用关系.当代码中出现异常的时候,我们就可以使用 e.printStackTrace(); 的方式查看出现异常代码的调用栈.

        如果本方法中没有合适的处理异常的方式,就会沿着调用栈向上传递

 public static void main(String[] args) {try {func();} catch (ArrayIndexOutOfBoundsException e) {e.printStackTrace();}System.out.println("after try catch");}public static void func() {int[] array = {1, 2, 3};System.out.println(array[100]);}//结果java.lang.ArrayIndexOutOfBoundsException: Index 100 out of bounds for length 3at LibrarySystem.func(LibrarySystem.java:107)at LibrarySystem.main(LibrarySystem.java:98)after try catch

        如果向上⼀直传递都没有合适的方法处理异常,最终就会交给JVM处理,程序就会异常终止(和我们最开始未使用trycatch时是⼀样的)

异常处理流程总结:

(1)程序先执行try中的代码

(2)如果try中的代码出现异常,就会结束try中的代码,看和catch中的异常类型是否匹配

(3)如果找到匹配的异常类型,就会执行catch中的代码

(4)如果没有找到匹配的异常类型,就会将异常向上传递到上层调用者

(5)无论是否找到匹配的异常类型,finally中的代码都会被执行到(在该方法结束之前执行)

(6)如果上层调用者也没有处理的了异常,就继续向上传递

(7)⼀直到main方法也没有合适的代码处理异常,就会交给JVM来进行处理,此时程序就会异常终止

二、自定义异常类

        Java 中虽然已经内置了丰富的异常类,但是并不能完全表示实际开发中所遇到的⼀些异常,此时就需要维护符合我们实际情况的异常结构

例如,我们实现⼀个用户登陆功能:

 public class LogIn {private String userName = "admin";private String password = "123456";public void loginInfo(String userName, String password) {if (!this.userName.equals(userName)) {System.out.println("⽤⼾名错误!");return;}if (!this.password.equals(password)) {System.out.println("密码错误!");return;}System.out.println("登陆成功");}public static void main(String[] args) {LogIn logIn = new LogIn();logIn.loginInfo("admin111", "123456");}}

        此时我们在处理用户名密码错误的时候可能就需要抛出两种异常.我们可以基于已有的异常类进行扩展 (继承),创建和我们业务相关的异常类

1、实现自定义异常类

具体方式:

(1)自定义异常类,然后继承自Exception或者RunTimeException

(2)实现⼀个带有String类型参数的构造方法,参数含义:出现异常的原因

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

此时我们的LogIn代码可以改成:

public class LogIn {private String userName = "admin";private String password = "123456";public void loginInfo(String userName, String password)  throws UserNameException,PasswordException{if (!this.userName.equals(userName)) {throw new UserNameException("用户名错误!");}if (!this.password.equals(password)) {throw new PasswordException("用户名错误!");}System.out.println("登陆成功");}public static void main(String[] args) {try {LogIn login = new LogIn();login.loginInfo("admin", "123456");} catch (UserNameException e) {e.printStackTrace();} catch (PasswordException e) {e.printStackTrace();}}}

#注:

(1)自定义异常通常会继承自Exception或者RuntimeException

(2)继承自Exception的异常默认是受查异常

(3)继承自RuntimeException的异常默认是非受查异常

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

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

相关文章

自建开发工具IDE(一)之拖找排版—仙盟创梦IDE

自建拖拽布局排版在 IDE 中的优势及初学者开发指南在软件开发领域,用户界面(UI)的设计至关重要。自建拖拽布局排版功能为集成开发环境(IDE)带来了诸多便利,尤其对于初学者而言,是踏入开发领域的…

GitHub Copilot - GitHub 推出的AI编程助手

本文转载自:GitHub Copilot - GitHub 推出的AI编程助手 - Hello123工具导航。 ** 一、GitHub Copilot 核心定位 GitHub Copilot 是由 GitHub 与 OpenAI 联合开发的 AI 编程助手,基于先进大语言模型实现代码实时补全、错误检测及文档生成,显…

基于截止至 2025 年 6 月 4 日,在 App Store 上进行交易的设备数据统计,iOS/iPadOS 各版本在所有设备中所占比例详情

iOS 和 iPadOS 使用情况 基于截止至 2025 年 6 月 4 日,在 App Store 上进行交易的设备数据统计。 iPhone 在过去四年推出的设备中,iOS 18 的普及率达 88。 88% iOS 188% iOS 174% 较早版本 所有的设备中,iOS 18 的普及率达 82。 82% iOS 189…

云计算-k8s实战指南:从 ServiceMesh 服务网格、流量管理、limitrange管理、亲和性、环境变量到RBAC管理全流程

介绍 本文是一份 Kubernetes 与 ServiceMesh 实战操作指南,涵盖多个核心功能配置场景。从 Bookinfo 应用部署入手,详细演示了通过 Istio 创建 Ingress Gateway 实现外部访问,以及基于用户身份、请求路径的服务网格路由规则配置,同时为应用微服务设置了默认目标规则。 还包…

Vue 3项目中的路由管理和状态管理系统

核心概念理解 1. 整体架构关系 这两个文件构成了Vue应用的导航系统和状态管理系统: Router(路由):控制页面跳转和URL变化Store(状态):管理全局数据和用户状态两者协同工作实现权限控制 2. 数据流…

Linux Capability 解析

文章目录1. 权限模型演进背景2. Capability核心原理2.1 能力单元分类2.2 进程三集合2.3 文件系统属性3. 完整能力单元表4. 高级应用场景4.1 能力边界控制4.2 编程控制4.3 容器安全5. 安全实践建议6. 潜在风险提示 1. 权限模型演进背景 在传统UNIX权限模型中,采用二进…

vue 监听 sessionStorage 值的变化

<template><div class"specific-storage-watcher"><h3>仅监听 userId 变化</h3><p>当前 userId: {{ currentUserId }}</p><p v-if"changeRecord">最近变化: {{ changeRecord }}</p><button click"…

IDEA:控制台中文乱码

目录一、设置字符编码为 UTF-8一、设置字符编码为 UTF-8 点击菜单 File -> settings -> Eitor -> File Encodings , 将字符全局编码、项目编码、配置文件编码统一设置为UTF-8, 然后点击 Apply 应用设置&#xff0c;点击 OK 关闭对话框:

[Sql Server]特殊数值计算

任务一&#xff1a;求下方的Num列的中值:参考代码:use Test go SELECT DISTINCTPERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY Num) over()AS MedianSalary FROM MedianTest;任务二: 下方表中,每个选手有多个评委打分&#xff0c;求每个选手的评委打分中值。参考代码:use Tes…

01-Docker概述

Docker 的主要目标是:Build, Ship and Run Any App, Anywhere,也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理,使用户的 APP 及其运行环境能做到一次镜像,处处运行。 Docker 运行速度快的原因: 由于 Docker 不需要 Hypervisor(虚拟机)实现硬件资源虚拟化…

Laravel中如何使用php-casbin

一、&#x1f680; 安装和配置 1. 安装包 composer require casbin/laravel-authz2. 发布配置文件 php artisan vendor:publish这会生成两个重要文件&#xff1a; config/lauthz.php - 主配置文件config/lauthz-rbac-model.conf - RBAC 模型配置文件 3. 运行数据库迁移 php…

算法题打卡力扣第4题:寻找两个正序数组的中位数(hard))

题目描述 提示&#xff1a; nums1.length m nums2.length n 0 < m < 1000 0 < n < 1000 1 < m n < 2000 -106 < nums1[i], nums2[i] < 106 解答思路 我的想法是先归并排序再直接返回下标中位数 代码 double findMedianSortedArrays(int* nums1,…

无人机抗噪模块技术概述!

一、 技术要点1. 传感器数据融合与滤波&#xff08;解决感知噪声&#xff09;核心思想&#xff1a;单一传感器易受干扰且不全面&#xff0c;通过融合多种传感器&#xff08;IMU惯性测量单元、GPS、气压计、磁力计、视觉传感器、激光雷达等&#xff09;的数据&#xff0c;利用算…

Horse3D游戏引擎研发笔记(六):在QtOpenGL环境下,仿Unity的材质管理Shader绘制四边形

在上一篇笔记中&#xff0c;我们已经实现了基于QtOpenGL的BufferGeometry管理VAO和EBO绘制四边形的功能。这一次&#xff0c;我们将深入探讨材质管理系统的实现&#xff0c;包括Shader的加载与编译、材质的创建与使用&#xff0c;以及如何通过材质系统绘制带有自定义Shader效果…

MySQL-分库分表(Mycat)

目录 1.介绍​ 概述 拆分策略 垂直拆分​ 水平拆分​ 实现技术​ shardingJDBC: MyCat: 2.Mycat概述 环境准备​ 分片配置 schema.xml​ server.xml 启动服务​ 分片测试​ 3.MyCat配置 schema.xml​ schema标签 datanode标签 ​datahost标签​ rule.xml …

Dubbo 的 Java 项目间调用的完整示例

1. 项目结构假设项目分为三个模块&#xff1a;api&#xff1a;定义服务接口provider&#xff1a;服务提供者consumer&#xff1a;服务消费者2. 依赖配置在 pom.xml 中添加 Dubbo 和注册中心&#xff08;如 Nacos&#xff09;的依赖&#xff1a;<dependency><groupId&g…

Python进行中文分词

1. jieba库概述 jieba&#xff08;“结巴”&#xff09;是Python中最流行的中文分词库&#xff0c;采用基于前缀词典实现的高效分词算法&#xff0c;支持多种分词模式&#xff0c;是中文自然语言处理(NLP)的基础工具。 核心特性 精确模式&#xff1a;试图将句子最精确地切开&am…

JavaScript 性能优化实战:从原理到落地的完整指南

一、引言&#xff1a;为什么 JavaScript 性能优化至关重要&#xff1f;性能与用户体验的强关联数据支撑&#xff1a;加载延迟每增加 1 秒&#xff0c;用户转化率下降 7%&#xff08;来自 Google 研究&#xff09;核心痛点&#xff1a;现代 Web 应用中 JS 代码体积膨胀、运行时卡…

前端自动化部署

摘要&#xff1a;前端自动化部署是通过工具和流程自动化实现前端代码从开发完成到线上发布的全流程&#xff0c;减少人工操作、提高效率并降低出错风险。核心目标减少重复操作&#xff1a;自动化构建、测试、部署等步骤&#xff0c;替代手动上传服务器等低效方式。提升发布效率…

peewee中db.create_tables(tables, safe=True),safe=True作用

db.create_tables(tables, safeTrue) 中的 safeTrue 参数的作用是 防止在表已经存在的情况下引发错误。 具体来说&#xff1a; 当 safeTrue 时&#xff1a;Peewee 会在生成的 SQL 语句中加入 IF NOT EXISTS 子句&#xff08;例如&#xff1a;CREATE TABLE IF NOT EXISTS my_tab…