Java初阶(异常)

news/2024/5/3 20:49:07/文章来源:https://blog.csdn.net/wuweixiaoyue/article/details/130000572

文章目录

  • 一、异常的结构体系
  • 二、异常的处理
    • 2.1 防御式编程
    • 2.2 异常的抛出
    • 2.4 异常的捕获(异常的具体处理方式)
      • (1)异常声明 throws
      • (2) 捕获处理 try-catch
    • 2.4 异常的处理流程
  • 三、自定义异常类

一、异常的结构体系

在Java中,将程序执行过程中发生的不正常行为称为异常,而java中不同类型的异常,都有与其对应的类来进行描述
在这里插入图片描述

  • Throwable:是异常体系的顶层类,其派生出两个重要的子类, Error 和 Exception
  • Error:指的是Java虚拟机无法解决的严重问题,比如:JVM的内部错误、资源耗尽等,典型代表:StackOverflowError和OutOfMemoryError,一旦发生回力乏术。
  • Exception:异常产生后程序员可以通过代码进行处理,使程序继续执行。比如:感冒、发烧。我们平时所说的异常就是Exception

二、异常的处理

2.1 防御式编程

  • 事前防御型(LBYL: Look Before You Leap.)
    • 在操作之前就做充分的检查
  • 事后认错型(EAFP: It’s Easier to Ask Forgiveness than Permission. ")
    • 先操作, 遇到问题再处理

2.2 异常的抛出

  • 概念
    正常情况下,我们的异常都是交给了JVM ,JVM一旦去处理 直接就是异常的终止程序
    而如果想要自定义地将异常抛出,我们就需要使用throw
  • 语法格式
    throw new XXXException(“异常产生的原因”);
public static int getElement(int[] array, int index){if(null == array){throw new NullPointerException("传递的数组为null");}if(index < 0 || index >= array.length){throw new ArrayIndexOutOfBoundsException("传递的数组下标越界");}return array[index];}public static void main(String[] args) {int[] array = {1,2,3};getElement(array, 3);
}
  • 注意事项
    • throw必须写在方法体内部
    • 抛出的对象必须是Exception 或者 Exception 的子类对象
    • 如果抛出的是 RunTimeException 或者 RunTimeException 的子类,则可以不用处理,直接交给JVM来处理
    • 如果抛出的是编译时异常,用户必须处理,否则无法通过编译
    • 异常一旦抛出,其后的代码就不会执行

2.4 异常的捕获(异常的具体处理方式)

(1)异常声明 throws

使用场景
处在方法声明时参数列表之后,当方法中抛出编译时异常,用户不想处理该异常,此时就可以借助throws将异常抛给方法的调用者来处理。即当前方法不处理异常,提醒方法的调用者处理异常。

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

}

class Person implements Cloneable{@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();     //表示会有个编译时的CloneNotSupportedException异常,}                      //但是这边并不想处理,于是只是用throws声明一下,异常的处理,交给方法的调用者(你要使用这个,就需要处理这个异常)
}
public class Main {public static void main(String[] args) throws CloneNotSupportedException{Person person1 = new Person();       //这边还是不想处理,所以再声明一下,这个异常最终会交给JVM处理,而一旦发生问题Person person2 = (Person)person1.clone();   //JVM就会异常终止}
}
  • 注意事项
    • throws必须跟在方法的参数列表之后
    • 声明的异常必须是 Exception 或者 Exception 的子类
    • 方法内部如果抛出了多个异常,throws之后必须跟多个异常类型,之间用逗号隔开,如果抛出多个异常类型
    • 具有父子关系,直接声明父类即可
    • 调用声明抛出异常的方法时,调用者必须对该异常进行处理,或者继续使用throws抛出(Alt + lnster 可以快速处理)

(2) 捕获处理 try-catch

使用场景
throws 其实最终并没有自定义处理,只是将异常报告给抛出异常方法的调用者,还是交给了JVM处理,如果要实现自定义处理,需要使用 try-catch 进行捕获

语法格式
try{
        // 将可能出现异常的代码放在这里
}catch(要捕获的异常类型 e){
        // 如果try中的代码抛出异常了,此处catch捕获时异常类型与try中抛出的异常类型一致时,或者是try中抛出异常的基类时,就会被捕获到
        // 对异常就可以正常处理,处理完成后,跳出try-catch结构,继续执行后序代码
}[catch(异常类型 e){
        // 对异常进行处理
}finally{
// 此处代码一定会被执行到
}]
// 后序代码
// 当异常被捕获到时,异常就被处理了,这里的后序代码一定会执行
// 如果捕获了,由于捕获时类型不对,那就没有捕获到,这里的代码就不会被执行

  • 注意:
    []中表示可选项,可以添加,也可以不用添加
    try中的代码可能会抛出异常,也可能不会
public class Main{public static void main(String[] args) {System.out.println("before");try {System.out.println(10/0);int[] array = null;System.out.println(array[2]);System.out.println("fdsfsafdsdsafsafsa");}/*catch (ArithmeticException | NullPointerException e) {System.out.println();        //不建议写在一起,因为这样就看不出来是什么异常了,可读性差}*/catch (ArithmeticException e) {e.printStackTrace();  //给出异常所在的行数System.out.println("捕获了ArithmeticException");}catch (NullPointerException e) {   //如果捕获了这个异常,就执行里面的语句e.printStackTrace();System.out.println("我捕获了空指针异常!");}}//异常的处理方式
//System.out.println(e.getMessage()); // 只打印异常信息
//System.out.println(e); // 打印异常类型:异常信息
//e.printStackTrace(); // 打印信息最全面
}

在这里插入图片描述

  • 注意事项
    • try块内抛出异常位置之后的代码将不会被执行(只能捕获一个异常)
    • 如果抛出异常类型与catch时异常类型不匹配,即异常不会被成功捕获,也就不会被处理,继续往外抛,直到JVM收到后中断程序----异常是按照类型来捕获的
    • catch 进行类型匹配的时候, 不光会匹配相同类型的异常对象, 也会捕捉目标异常类型的子类对象
      • 所以建议从下往上,先捕捉子类异常,再捕捉父类异常
public static void main(String[] args) {System.out.println("before");try {System.out.println(10/0);}catch (ArithmeticException e) {   //由于 Exception 类是所有异常类的父类.//因此可以用这个类型表示捕捉所有异常,但那样就看不出来是因为什么异常了,不推荐System.out.println("捕获了ArithmeticException");}catch (Exception e) {       System.out.println("我捕获到了:Exception!,这里一般处理异常");}System.out.println("after");}

❤️finally

使用场景:需要执行那些,即使出现了异常,也一定要执行的操作(eg.程序中打开的资源的需要回收的操作,异常会引发程序的跳转,可能导致有些语句执行不到)

语法格式
try{
        // 可能会发生异常的代码
}catch(异常类型 e){
        // 对捕获到的异常进行处理
}finally{
        // 此处的语句无论是否发生异常,都会被执行到
}
        // 如果没有抛出异常,或者异常被捕获处理了,这里的代码也会执行

什么时候 try-catch-finally 中的代码不会执行???
当 try - catch 中有return的时候,如下面

public static int getData(){Scanner sc = null;try{sc = new Scanner(System.in);int data = sc.nextInt();return data;}catch (InputMismatchException e){e.printStackTrace();}finally {System.out.println("finally中代码");}System.out.println("try-catch-finally之后代码");//如果正常输入,成功接收输入后程序就返回了,那么这里的代码就不会执行即输入流就没有被释放,造成资源泄漏if(null != sc){   sc.close();  //Scanner也是一种资源,需要释放,close方法可以释放Scanner}return 0;
}
public static void main(String[] args) {int data = getData();System.out.println(data);
}
  • 总结
    • 为了避免代码泄漏,我们可以利用finally中的代码一定会最后执行的这个特点,将资源清理的扫尾代码放在里面

两个 return 如何执行

public static void main(String[] args) {System.out.println(func());
}
public static int func() {try {return 10;} finally {return 20;}
}//20
  • 总结
    • finally 执行的时机是在方法返回之前(try 或者 catch 中如果有 return 会在这个 return 之前执行 finally).
    • 但是如果finally 中也存在 return 语句, 那么就会执行 finally 中的 return, 不会执行到 try 中原有的 return.
    • 一般我们不建议在 finally 中写 return (被编译器当做一个警告).

2.4 异常的处理流程

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

执行流程总结

  • 程序先执行 try 中的代码
  • 如果 try 中的代码出现异常, 就会结束 try 中的代码, 看和 catch 中的异常类型是否匹配.
  • 如果找到匹配的异常类型, 就会执行 catch 中的代码
  • 如果没有找到匹配的异常类型, 就会将异常向上传递到上层调用者(如果本方法中没有合适的处理异常的方式, 就会沿着调用栈向上传递)
  • 无论是否找到匹配的异常类型, finally 中的代码都会被执行到(在该方法结束之前执行).
  • 如果上层调用者也没有处理的了异常, 就继续向上传递.
  • 一直到 main 方法也没有合适的代码处理异常, 就会交给 JVM 来进行处理, 此时程序就会异常终止

三、自定义异常类

使用场景:Java 中提供的异常没有办法完全描述实际开发中所需要的异常,这时候就需要我们自定义异常类

实现方式
自定义异常类,然后继承自Exception(默认是受查异常) 或者 RunTimeException(非受查异常)
实现一个带有String类型参数的构造方法,参数含义:出现异常的原因

❤️继承的是Exception
如果是继承了Exception,就默认是受查异常,需要 throws 处理或者 try-catch 的异常处理

class PasswordException extends Exception{public PasswordException() {}public PasswordException(String message) {super(message);}
}class UserNameException  extends Exception{   
//自己写的类之所以说是异常类,是因为继承某个异常public UserNameException() {}public UserNameException(String message) {super(message);}
}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(userName+" 用户名错误!");//System.out.println("用户名错误!");    单纯的打印,定位不到问题在哪里//return;}System.out.println("登陆成功");}public static void main(String[] args) {LogIn logIn = new LogIn();try {    logIn.loginInfo("admin12", "123456111");}catch (UserNameException e) {e.printStackTrace();}catch (PasswordException e) {e.printStackTrace();}}
}

在这里插入图片描述

❤️继承的是RunTimeException

class UserNameException  extends RuntimeException{public UserNameException() {}public UserNameException(String message) {super(message);}
}public class Main {private String userName = "admin";private String password = "123";public  void loginInfo(String userName, String password) {if (!this.userName.equals(userName)) {throw new UserNameException(userName+" 用户名错误!");}System.out.println("登陆成功");}public static void main(String[] args) {Main logIn = new Main();logIn.loginInfo("admin12", "123456111");}
}

在这里插入图片描述

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

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

相关文章

go学习线路图

1. go学习线路图 1.1.2. 资源 先决条件 GoSQL 通用开发技能 学习 GIT&#xff0c;在 GitHub 上建立一些仓库&#xff0c;与其它人分享你的代码了解 HTTP(S) 协议&#xff0c;request 方法&#xff08;GET, POST, PUT, PATCH, DELETE, OPTIONS&#xff09;不要害怕使用 Google&a…

和数软件荣获上海市“专精特新”企业荣誉认定

近日&#xff0c;上海市经济和信息化委员会公示了2022年上海市“专精特新”企业名单。根据《关于组织开展2022年创新型中小企业评价、专精特新中小企业认定和复核工作的通知》&#xff08;沪经信企〔2022〕776号&#xff09;&#xff0c;经专家评审和综合评估&#xff0c;上海和…

学会吊打面试官之map

小白&#xff1a;大牛&#xff0c;我最近学习了一些C的STL容器&#xff0c;但是我还是有一些疑惑&#xff0c;特别是对于map&#xff0c;我不太理解它的底层实现和具体用法。能否跟我讲一下&#xff1f; 大牛&#xff1a;当然可以啊&#xff0c;map是一种非常常用的关联式容器…

小企业选择什么样的CRM系统比较合适,有什么特点?

CRM客户管理系统已经成为各种规模的企业&#xff0c;特别是小型企业的重要工具。CRM系统帮助小型企业更有效地管理客户数据和互动&#xff0c;简化销售流程&#xff0c;并提高客户满意度。市场上有如此多的选择&#xff0c;小企业该如何选择合适的CRM系统&#xff1f; 什么是C…

深圳CPDA|如何着手商业数据分析?

商业数据分析是一项非常重要的工作&#xff0c;可以帮助企业做出更明智的决策。 下面是一些着手商业数据分析的步骤&#xff1a; 1.确定你的问题 首先需要明确你想要解决什么问题。 这通常需要与业务团队沟通&#xff0c;以便了解他们正在寻找哪些信息。 2.收集数据 收集数…

linux语言学习记录

文章目录前言一、linux文件结构二、指令三、Gvim编辑器1、命令模式2、底行命令四、正则表达式1、表达式匹配举例2、对文件里面内容进行操作3、使用 \( 和 )\ 符号括起正规表达式&#xff0c;即可在后面使用\1和\2等变量来访问和中的内容前言 记录自己学习linux的笔记&#xff…

IFPUG功能点度量5:计算功能规模

功能点计数类型&#xff1a;开发项目、升级项目、应用 一、 三种功能能规模计算&#xff1a; 1、开发项目计算 DFP&#xff08;开发项目功能规模&#xff09;ADD&#xff08;交付用户的功能规模&#xff09;CFP&#xff08;转换功能的功能规模&#xff09; 2、升级项目计算 …

【代码笔记】Pytorch学习 DataLoader模块详解

Pytorch DataLoader模块详解dataloader整体结构DataLoaderinit 初始化参数解释代码解析IterableDataset 判断构建Sampler&#xff0c;单样本构建BatchSampler&#xff0c;组建batch构建collate_fn 对获取的batch进行处理其他的一些逻辑判断_get_iterator代码解析multiprocessin…

【Python】轻松掌握基础语法(一)

文章目录常量和表达式变量和类型变量的定义变量的使用变量的类型intfloatstrbool动态类型注释输入和输出输出输入运算符算数运算符关系运算符逻辑运算符赋值运算符其他常量和表达式 print(1 2 * 3)print是Python内置的一个函数&#xff0c;作用为输入打印到控制台形如1 2 * …

人工智能前沿——「全域全知全能」人类新宇宙ChatGPT

&#x1f680;&#x1f680;&#x1f680;OpenAI聊天机器人ChatGPT——「全域全知全能」人类全宇宙大爆炸&#xff01;&#xff01;&#x1f525;&#x1f525;&#x1f525; 一、什么是ChatGPT?&#x1f340;&#x1f340; ChatGPT是生成型预训练变换模型&#xff08;Chat G…

1.半导体基础知识

1.半导体基础知识本征半导体什么是半导体&#xff1f;什么是本征半导体&#xff1f;本征半导体的结构本征半导体中的两种载流子为什么将自然界导电性能中等的半导体材料制成本征半导体杂质半导体N型半导体P型半导体PN结PN结中的扩散运动漂移运动和PN结的形成PN结的单向导电性PN…

uniapp开发小程序-swiper点击预览大图(商品详情页轮播图)

1.实现效果&#xff1a; 2.具体代码&#xff1a; <view class"swiper_box"><!--轮播图--><swiper class"ms_swiper" :autoplay"true" circular"true" change"swiperChange"><swiper-item v-for"…

【动态规划模板】神似的01和完全背包、多重背包和分组背包问题

神似的01背包与完全背包&#x1f349; 【经典题目】01背包采药 题目描述 &#x1f388; 辰辰是个天资聪颖的孩子&#xff0c;他的梦想是成为世界上最伟大的医师。为此&#xff0c;他想拜附近最有威望的医师为师。医师为了判断他的资质&#xff0c;给他出了一个难题。医师把他…

【Redis学习】SpringBoot集成Redis

总体概述 jedis-lettuce-RedisTemplate三者的联系 本地Java连接Redis常见问题 bind配置请注释掉 保护模式设置为no Linux系统的防火墙设置 redis服务器的IP地址和密码是否正确 忘记写访问redis的服务端口号和auth密码 集成jedis 简介 Jedis Client是Redis官网推荐的一个面…

【c语言】文件的读写

文件读写使用二进制读写比较方便&#xff0c;分别使用fread和fwrite函数进行。 一、函数定义 以二进制形式读取文件&#xff0c;从stream流中读取内容&#xff0c;读到ptr指向的空间中&#xff0c;读取size大小的count个内存单元。 返回值为读取到的字符个数。 以二进制形式读…

解决Abp设置DefaultLanguage默认语言不生效的问题

文章目录现象原因分析解决问题现象 默认地&#xff0c;Abp的语言提供程序将返回的CultureInfo为En&#xff0c;在一些默认实现的接口&#xff08;比如/api/TokenAuth/Authenticate&#xff09;返回的错误信息是英文 目标是改成简体中文显示&#xff0c;但是即便我们在AbpSett…

android framework-zygote进程

Zygote进程&#xff1a;可以看到zygote的父进程是init进程 一、Zygote整体时序图 涉及源码路径 android-10.0.0_r41\frameworks\base\cmds\app_process\Android.mk android-10.0.0_r41\frameworks\base\cmds\app_process\app_main.cpp android-10.0.0_r41\frameworks\base\core…

图像阈值化

图像阈值化 图像阈值化简介 ⚫ 图像阈值化是图像处理的重要基础部分, 应用很广泛, 可以根据灰度差异来分割图像不同部分 ⚫ 阈值化处理的图像一般为单通道图像(灰度图) ⚫ 阈值化参数的设置可以使用滑动条来debug ⚫ 阈值化处理易光照影响, 处理时应注意 ⚫ 本节主要介绍…

1000题!!阿里P8架构师手写“Java面试宝典”带你横扫全网

序言 很多同学学习Java并发一头扎进源码&#xff0c;最后头破血流&#xff0c;无功而返。横看成岭侧成峰&#xff0c;远近高低各不同。学习要始终从不同的视角来看待问题。学习并发亦是如此&#xff0c;需要通过理论远看轮廓&#xff0c;然后通过源码近看明细。 今天小编分享…

Java之堆和堆排序

目录 一.什么是堆 1.基本介绍 2.堆的实现方式 二.最大堆的实现 1.最大堆 2.思路分析 0.基础操作 1.添加上浮操作 2.删除下沉操作 3.将数组堆化操作 2.代码实现 三.堆排序 1.什么是堆排序 2.思路分析 3.代码实现 一.什么是堆 1.基本介绍 堆是一种数据结构&#…