当前位置: 首页 > news >正文

Java、从零开始学异常

📚 目录

  • 1.什么是异常
    1.1异常的分类
    1.2throw与throws
  • 2.处理异常
    2.1防御型编程
    2.2捕获异常try catch
    2.3finally
  • 3.自定义异常
    3.1为什么需要自定义异常
    3.2自定义异常的实现步骤


前言:
接触 Java 编程,大家大概率都会遇到这样的情况:写好的代码一运行,控制台就弹出满屏红字,也就是我们说的异常。它只是 Java 提示我们程序出错的一种方式。

1. 什么是异常

程序员日常开发的过程中,绞尽脑汁想,怎么去优化,怎么去修改代码,难免会出现一些特殊情况。这种情况我们就称之为异常。
举个简单的例子:

可以简单理解为:意想不到的状况。

🔙 返回目录




1.1 异常的分类

前期学习过程中我们遇到过比较多的异常为:
空指针异常:NullPointerException

publicclassTest{publicstaticvoidmain(String[]args){Strings=null;System.out.println(s.length());}}

示例:

算数异常:ArithmeticException

publicclassTest{publicstaticvoidmain(String[]args){System.out.println(1/0);}}

示例:

数组越界异常:ArrayIndexOutOfBoundsException

publicclassTest{publicstaticvoidmain(String[]args){char[]array=newchar[10];System.out.println(array[100]);}}

示例:

总体上我们能分为受查异常/编译型异常 、非受查异常/运行时异常

异常分类图:

今天我们主要将异常。
StackOverflowError:可以简单理解为:方法炸了(递归太深)
OutOfMemoryError :可以简单理解为:对象炸了(对象太多)
所举例的只是编译时异常的其中一种:
编译时异常/受查异常:编译不会通过,编译器会出现红色的波浪线。
运行时异常/非受查异常:编译能够通过,运行时候出现的错误,比如栈溢出,堆溢出等等一系列的错误。

🔙 返回目录




1.2 throw与throws

异常的抛出:throw

thrownew异常("原因")

使用举例:

publicstaticvoidfunc(char[]array,intn){if(array==null){thrownewNullPointerException("数组为null");}if(n>array.length){thrownewArrayIndexOutOfBoundsException("长度超出范围");}}}

注意事项:
throw必须写在方法内部。
抛出的异常必须为Exception或者其子类。
抛出的是编译型异常,用户必须要处理这个异常,否则编译不能正常通过,程序不能正常运行。

处理异常。
这种处理异常的方式指标不治本,当调用这个方法的类也需要处理异常。只是让程序能通过编译。

会传递异常,要是没有一个解决就交给JVM解决。

异常的声明:throws

修饰符 返回类型 方法名字(参数列表)throws声明的异常...{}

使用举例:

publicstaticvoidfunc(char[]array,intn)throwsNullPointerException,ArrayIndexOutOfBoundsException{if(array==null){thrownewNullPointerException("数组为null");}if(n>array.length){thrownewArrayIndexOutOfBoundsException("长度超出范围");}}}

只是告诉调用者可能会出现这些异常。实际上会将解决办法传递给调用者
注意事项:
throws必须写在方法参数列表后面。
抛出的异常必须为Exception或者其子类。
多个异常可以用逗号隔开,如果抛出多个异常具有父子类关系,只需要声明父类异常即可。

🔙 返回目录




2. 处理异常

简单来说就是给用户兜底,保证用户的使用,方便程序员处理问题。
比如:我们打个游戏网络波动掉线了,系统会出现重新连接的这个处理异常的方法。

🔙 返回目录




2.1 防御型编程

例如:

publicclassTest{publicstaticvoidfunc3(int[]array,inta){if(a==0){//处理异常}if(a==100){//处理异常}}}

事发前就已经知道了要发生的异常,提前防范。

🔙 返回目录




2.2 捕获异常try catch

捕获到异常后,我们就能处理这个异常。
使用举例:

publicclassTest{publicstaticintfunc(intn){return2/n;}publicstaticvoidmain(String[]args){try{intret=func(0);}catch(ArithmeticExceptione){e.printStackTrace();System.out.println("处理方法...");}System.out.println("后续代码继续执行...");}}

我们可以使用多个catch去捕获异常。
使用e.printStackTrace();可以打印我们的错误信息栈。方便我们查找。

异常被处理完之后代码依旧会往下继续执行。

具体处理逻辑,需要根据我们的业务来进行确定。
当没有满足这个异常的时候,就会交给JVM来执行,程序就会中断执行。
我们也可以把异常写到一行:用 | 来实现。

异常后面的名字不一定是e也可以叫别的名字。按照自己喜好来设置。

🔙 返回目录




2.3 finally

finally用来善后:不管抓到什么异常finally里面的代码都会被执行。

*/publicclassTest{publicstaticintfunc(intn){return2/n;}publicstaticvoidmain(String[]args){try{intret=func(0);}catch(ArithmeticException|NullPointerExceptione){e.printStackTrace();System.out.println("处理方法...");}finally{System.out.println("finally被执行了....");}System.out.println("后续代码继续执行...");}}


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

使用finally可以关闭一些不使用的程序,防止资源浪费。
finally中的代码⼀定会执行的,⼀般在finally中进行一些资源清理的扫尾工作。
异常处理图:

程序先会执行try中语句,如果发生异常,就会去catch中寻找,找到相互匹配的异常之后就会执行catch中的语句去处理异常,如果没有找到相互匹配的异常就会交给调用者来处理,如果调用者也没有对其处理就会交给JVM进行处理,此时程序崩溃/终止,无论catch语句是否执行,finally语句一定会被执行。

🔙 返回目录




3. 自定义异常

Java官方可能给我们提供所有的异常种类,此时就需要我们自己去定义异常。

🔙 返回目录



3.1 为什么需要自定义异常

当问出为什么会有异常的时候,就像别人问你为什么会有类这个东西?
为什么会有异常?
实际开发过程中Java官方提供的异常,不能解决我们实际开发过程中的问题。
就比如打游戏打到一半,网络掉线了,此时Java官方并没有给出这个一个异常,就需要我们自定义异常。

🔙 返回目录




3.2 自定义异常的实现步骤

不知道怎么定义一个异常?
我们可以去模仿Java官方给我们的异常写法。

首先我们需要继承Exception。继承Exception的异常是编译时异常/受查异常。
继承 RuntimeException默认为运行时异常。
我们以 RuntimeException为例:
定义异常:模拟实现简单的登录。
密码异常:

publicclassPasswordExceptionextendsRuntimeException{publicPasswordException(){super();}publicPasswordException(Strings){super(s);}}

用户名异常:

publicclassUsernameExceptionextendsRuntimeException{publicUsernameException(){super();}publicUsernameException(Strings){super(s);}}

模拟登录:

classLogin{privateStringname="daxiong";privateStringpassworld="123456";publicvoidlogin(Stringname,Stringpassworld){if(!this.name.equals(name)){thrownewUsernameException();}if(!this.passworld.equals(passworld)){thrownewPasswordException();}System.out.println("登录成功...");}}

实现登录:用try catch捕获异常。

publicclassTest{publicstaticvoidmain13(String[]args){Loginlogin=newLogin();try{login.login("daxiong","123456");}catch(PasswordExceptione){System.out.println("密码错误");e.printStackTrace();}catch(UsernameExceptione){System.out.println("用户名错误");e.printStackTrace();}}}
🔙 返回目录




http://www.jsqmd.com/news/598459/

相关文章:

  • FinalBurn Neo终极指南:3步快速开启你的复古街机游戏之旅
  • PHP防止Shell命令注入的有效方法
  • 无片外电容LDO电路设计 完整IP现成电路,具有过温保护和过流保护,带隙,BUFFER都有 性...
  • 告别手动编译!用SDKManager一键为Jetson Orin NX刷入JetPack 6.2.1并开启实时内核
  • 【实战指南】迪文屏开发全流程解析与优化技巧
  • Florence-2 视觉语言模型适配 Neuron SDK 全记录:Stage-wise 编译与 Bucket 策略实战
  • 终极方案:如何用代码替代拖拽,高效绘制专业架构图与流程图
  • 告别固定阈值!用DBnet做文本检测,手把手教你搞定自适应二值化(附PyTorch代码)
  • 如何快速配置虚拟手柄驱动:面向游戏玩家的完整教程
  • 低代码技术如何重构钣金工厂的数字化生产链路
  • 深入MAX30102传感器:从光电信号到心率血氧值的完整数据处理流程解析
  • 智慧机场三维空间智能中枢系统白皮书——构建“全域感知 × 空间认知 × 智能调度”的下一代机场操作平台
  • 新手必看:5分钟搞定Linux服务器基础命令行操作(含常见问题解决)
  • 告别CSDN限制!VScode+PicGo+Github图床保姆级配置指南(支持Markdown写作)
  • Wan2.2-I2V-A14B效果实测:不同prompt下视频连贯性、画质、运动自然度分析
  • 伺服压力机与MCGS、昆仑通态触摸屏:实时曲线、历史数据存盘与完整PLC程序功能概述
  • Text-to-SQL实战:如何用RSL-SQL在5分钟内提升数据库查询准确率(附避坑指南)
  • Atcoder abc452_e 笔记
  • DCDC电源带载不稳?5个常见坑点及实测排查指南(附波形分析)
  • 从Fetch到SSE:我的大模型前端对接踩坑实录(附性能对比表格)
  • 智慧车站三维空间智能管控系统白皮书——构建“全域感知 × 连续认知 × 动态调度”的交通枢纽空间智能中枢
  • 告别启动黑屏:RK3568设备树中bootargs的PARTUUID到底该怎么写?(附完整配置流程)
  • gcc-multilib安装指南:解决Linux编译中的‘fatal error: sys/cdefs.h‘问题
  • 别再花冤枉钱!实测鼎阳SDS2000X+示波器软件选件‘激活’全流程(附在线脚本工具)
  • 微信聊天记录导出恢复/备份/离线查看工具(支持最新版4.1及以上)
  • 用STM32的TIMER搞定无刷电机HALL测速与换相(附代码避坑)
  • 如何通过社交媒体提高 SEO 关键词排名_如何利用地理位置优化 SEO 关键词排名
  • 华为防火墙GRE隧道配置避坑指南:为什么你的Tunnel接口ping不通?
  • 手把手教你移植STM32贪吃蛇到你的2.4寸TFT屏(附完整工程与避坑指南)
  • 为什么一个非常大的数的导数是一个非常小的数?