【Java编程进阶】Java异常详解

news2024/11/23 11:00:02

在这里插入图片描述

推荐学习专栏:Java 编程进阶之路【从入门到精通】,从入门到就业精通,买不了吃亏,买不了上当!!


文章目录

  • 1. 异常
  • 2. 异常的体系
  • 3. Error
  • 4. 异常产生的过程
  • 5. throw 关键字
  • 6. 异常处理
    • 6.1 throws 关键字
    • 6.2 try...catch 捕获异常
  • 7. 获取异常信息
  • 8. finally 代码块
  • 9. 自定义异常
  • 10 Java编程基础教程系列

1. 异常

异常就是不正常的意思,是程序执行过程中出现的非正常情况,最终导致 JVM 非正常终止。异常是 Java 中提供的一种识别及响应错误情况的一致性机制。有效地异常处理能使程序更加健壮、易于调试。

在这里插入图片描述
在Java语言中,将程序执行中发生的不正常情况称为异常 , 开发过程中的语法错误和逻辑错误不是异常,此时无法通过编译,程序无法运行,异常是指程序运行过程中的问题。

示例:

public class Test {
    public static void main(String[] args) {
        int a = 10;
        int b = 0;
        int c = a / b;

        System.out.println(a + "/" + b + "=" + c);
    }
}

当程序运行到int c = a / b时,JVM 会 new 一个异常对象:

new ArithmeticException("/ by zero");

并且 JVM 将异常对象抛出,打印输出信息到控制台。

在这里插入图片描述

Java 中异常发生的原因有很多,例如:

  • 用户输入了非法数据
  • 要打开的文件不存在
  • 网络通信时连接中断
  • JVM内存溢出
  • 这些异常有的是因为用户错误引起,有的是程序错误引起的,还有其它一些是因为物理错误引起的。

2. 异常的体系

Java 异常其实是为了帮助我们找到程序中的问题,其本质其实是一个类,产生异常就是创建异常对象并抛出这个异常对象。

异常的根类是 Java.lang.Trowable,是所有异常和错误是超类,其有两个子类,分别是 Error 类和 Exception 类。平时我们常说的异常主要是这里的 Exception 类,这里也主要是对该类就行讲解。

在这里插入图片描述

Exception 类是指编译期异常类,即编译Java代码即写代码期出现的问题,其子类 RutimeException 类称为运行期异常,指 Java 运行中出现的问题,只要我们处理掉异常,程序就可以继续执行。Error 类是程序无法处理的错误,表示运行应用程序中较严重问题。

Java异常分为可查异常和不可查异常。正确的程序在运行过程中,很容易出现情理可容的异常状况。可查异常虽然是异常状况,但在一定程度上它的发生是可以预计的,而且一旦发生这种异常状况,就必须采取某种方式进行处理。

除了 RuntimeException 及其子类以外,其他的Exception类及其子类都属于可查异常,最典型的是IO类异常。

RuntimeException 与其子类和错误 Error 属于不可查异常,编译器不要求强制处置的异常。

3. Error

Error 是指系统内部的错误,这类错误由系统进行处理,程序本身无需捕获处理。比如:内存溢出错误OOM,堆栈溢出错误StackOverflowError等,一般发生这种情况,JVM会选择终止程序。此时必须修改代码,程序才能执行。

示例:

//堆栈溢出错误
public class Test {
    public static void recursionMethod() {
        recursionMethod();// 无限递归下去
    }
    public static void main(String[] args) {
        recursionMethod();
    }
}

报错信息:

Exception in thread "main" java.lang.StackOverflowError
	at Test.recursionMethod(Test.java:4)
	at Test.recursionMethod(Test.java:4)
	at Test.recursionMethod(Test.java:4)
	at Test.recursionMethod(Test.java:4)
    ...

4. 异常产生的过程

通过了解异常产生的过程我们可以深入学习如何处理异常,通过下面的例子来学习异常产生的过程,定义一个数组,定义一个获取数组指定索引位置元素的值,此时程序就有可能产生数组索引越界的异常:

public class Test {
    public static void main(String[] args) {
        int[] arr={1,2,3};
        int b=getElement(arr,3);
        System.out.println(b);
    }
    public static int getElement(int[] arr,int index){
        int a=arr[index];
        return a;
    }
}

异常信息:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
	at Test.getElement(Test.java:8)
	at Test.main(Test.java:4)

程序在执行 getElement() 方法时,传入了 arr 和3两个参数,目的是访问数组 arr 索引为3的元素的值,但是由于数组 arr 的长度为3,此时 JVM就会检测到程序出现了异常,JVM执行一下操作:

第一步: JVM根据异常的原因创建了一个异常的对象,包含了异常产生的内容,原因和位置。

new ArrayIndexOutOfBoundsException("3");

第二步:因为 getElement() 方法中没有异常处理的逻辑(try…catch),所以 JVM 把异常对象抛给了该方法的调用者 main 方法来处理这个异常。

当 main 方法接收到这个异常对象后,由于它也没有异常处理的逻辑,所以继续把异常对象抛给了 main 方法的调用者 JVM 来处理。当 JVM 接收到这个异常对象后,首先把异常对象的内容输出打印在控制台,其次采用中断处理,结束这个 Java 程序。

5. throw 关键字

我们可以使用 throw 在指定的方法中抛出异常,使用时必须写在方法的内部,且 throw 后创建的对象必须是 Exception 类的对象或者是其子类的对象。

throw 抛出异常后,我们必须处理这个异常,如果 throw 后创建的是 RuntimeException 类或者其子类的对象,我们可以不处理,默认交给 JVM 处理,即打印异常,中断程序。如果创建的是编译时(写代码时)异常对象,此时必须使用 throws 或者 try…catch 来处理异常。

示例:在定义一个方法时,我们要先对方法传递的参数进行合法性校验,如果传递的参数不合法,我们就要使用抛出异常的方法告知方法的调用者参数不合法。

public class Test {
    public static void main(String[] args) {
        int[] arr=null;
        int b=getElement(arr,3);
        System.out.println(b);
    }
    public static int getElement(int[] arr,int index){
        if(arr==null) {
            throw new NullPointerException("传递的数组为空");
        }
        if(index<0||index>=arr.length){
            throw new ArrayIndexOutOfBoundsException("传递的参数超出数组下标") ;
        }
        int a=arr[index];
        return a;
    }
}

此时,由于传入的数组为空值,且new NullPointerException("传递的数组为空")为运行时异常类的对象,所以异常信息会被打印在控制台,并且中断程序。

6. 异常处理

6.1 throws 关键字

使用 throws 关键字处理异常是今天要谈论的异常处理的第一种方式。前面说到,在方法中使用 throw 抛出异常对象后,必须处理这个异常对象,此时我们就可以使用 throws 把这个异常对象抛给方法的调用者,最终抛给 JVM 做中断处理。

使用 throws 关键字有以下几个注意事项:

  • throws 必须写在方法声明后面
  • throws 关键字后面使用的必须是 Exception 类或者其子类
  • 方法体中抛出多个异常对象就要在 throws 后面声明多个异常,如果方法体中抛出的异常有字父类的关系,则只需要声明父类异常

当我们调用了声明异常的方法后,就必须对这个异常进行处理,要么继续使用 throws 抛出异常对象交给方法的调用者处理,最终由 JVM 做中断处理。要么使用 try…catch 自己处理异常。

示例:定义一个方法,对方法输入的文件路径的参数做合法性判断。

import java.io.FileNotFoundException;

public class Test {
    public static void main(String[] args) throws FileNotFoundException {
        //定义一个方法,对传递的路径参数做合法性校验
        readFile("c://b.txt");
    }

    public static void readFile(String fileName) throws FileNotFoundException {
        if (!(fileName.equals("c://a.txt"))) {
            throw new FileNotFoundException("传递的文件路径不是c://a.txt");
        }
    }
}

此时,如果 readFile() 方法传入的参数不是 "c://a.txt" ,程序运行到调用该方法的位置时,JVM 对程序做中断处理,打印异常内容到控制台。

在这里插入图片描述

6.2 try…catch 捕获异常

现在要谈论的是异常处理的第二种方法,使用 try…catch 捕获异常。前面我们使用 throws 声明异常,显然是有局限性的,程序运行到调用声明异常的方法时,如果程序出现异常,则后序代码不会执行。而此方法可以对程序中出现的问题做指定方式的处理。

语法:

try{
    //可能出现异常的代码
}catch(){//括号中定义异常变量,用来接收try中抛出的异常对象,try中抛出多个异常对象,可以使用多个catch处理异常对象
    //异常处理逻辑
   }

如果 try 中出现了异常,就会抛出异常对象并执行 catch 中的语句,执行完继续执行 try…catch 后的语句。否则不会执行 catch 中的语句,执行完 try 中的语句直接执行 try…catch 后的语句。

示例:定义一个方法,对方法输入的文件路径的参数做合法性判断,如果出现异常,则捕获异常。

import java.io.FileNotFoundException;

public class Test {
    public static void main(String[] args) {
        try {
            //定义一个方法,对传递的路径参数做合法性校验
            readFile("c://b.txt");
        } catch (FileNotFoundException e) {
            System.out.println("传递的文件路径不是c://a.txt");
        }
        System.out.println("后续代码");
    }

    public static void readFile(String fileName) throws FileNotFoundException {
        if (!(fileName.equals("c://a.txt"))) {
            throw new FileNotFoundException("传递的文件路径不是c://a.txt");
        }
    }
}

此时,如果 readFile() 方法中传入的参数不是 c://txt ,则捕获异常给 catch 中的语句块做异常处理,执行完以后继续执行 try…catch 后面的语句。

在这里插入图片描述

7. 获取异常信息

Throwable 中定义了三个方法用于获取异常信息,分别是:

  • public String getMessage() 返回 Trowable 的简短描述
  • public String toString() 返回 trowable 的详细描述
  • public String printStackTrace JVM 打印异常信息默认调用此方法,其描述最详细,包括异常产生的内容原因和位置

示例1:使用 getMessage() 方法获取异常信息

import java.io.FileNotFoundException;

public class Test {
    public static void main(String[] args) {
        try {
            //定义一个方法,对传递的路径参数做合法性校验
            readFile("c://b.txt");
        } catch (FileNotFoundException e) {
            System.out.println(e.getMessage());
        }
    }

    public static void readFile(String fileName) throws FileNotFoundException {
        if (!(fileName.equals("c://a.txt"))) {
            throw new FileNotFoundException("传递的文件路径不是c://a.txt");
        }
    }
}

此时,如果程序出现异常,异常信息显示为:

在这里插入图片描述

示例2:使用 toString() 方法获取异常信息

 try {
            //定义一个方法,对传递的路径参数做合法性校验
            readFile("c://b.txt");
        } catch (FileNotFoundException e) {
            System.out.println(e.toString());
        }

异常信息为:

在这里插入图片描述

示例3:使用 printStackTrace() 方法获取异常信息:

 try {
            //定义一个方法,对传递的路径参数做合法性校验
            readFile("c://b.txt");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

此时的异常信息为:

在这里插入图片描述

8. finally 代码块

在使用 try…catch 捕获异常时,如果 try 中代码出现了异常,则创建异常对象抛给 catch 语句块中的异常处理逻辑代码处理,此时 try 中后续的代码将不会执行。有时我们需要这个位置的代码继续执行,例如需要释放资源,则出现了 fianlly 代码块。

无论程序是否出现异常,finally 代码块中的代码都会执行。且 finally 不可以单独使用,必须使用在 try 代码后,后序 IO 流中继续学习。

示例:

import java.io.FileNotFoundException;

public class Test {
    public static void main(String[] args) {
        try {
            //定义一个方法,对传递的路径参数做合法性校验
            readFile("c://b.txt");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }finally {
            System.out.println("资源释放");
        }
    }

    public static void readFile(String fileName) throws FileNotFoundException {
        if (!(fileName.equals("c://a.txt"))) {
            throw new FileNotFoundException("传递的文件路径不是c://a.txt");
        }
    }
}

此时,程序出现了异常,但是 finally 中的语句继续执行。

java.io.FileNotFoundException: 传递的文件路径不是c://a.txt
	at Test.readFile(Test.java:17)
	at Test.main(Test.java:7)
资源释放

9. 自定义异常

系统定义的异常主要用来处理系统可以预见的常见运行错误,对于某个应用所特有的运行错误,需要编程人员根据特殊逻辑来创建自己的异常类。

例如在我们输入成绩的时候,往往会有一个范围,而这个范围不是JVM能够识别的,此时就需要自己定义异常类。

语法格式:

public class 自定义异常类名 extends Exception{}

使用继承 Exception 类的类定义自定义异常逻辑类,而 Exception 中常用的构造方法也可以被子类用super调用。同样还可以使用继承自 runtimeException 类的类实现运行时的自定义异常类。

示例:

//栈操作异常:自定义异常!
public class StackOperationException extends Exception{ // 编译时异常!
    public MyStackOperationException(){

    }

    public MyStackOperationException(String s){
        super(s);
    }
}

10 Java编程基础教程系列

【Java编程进阶】封装继承多态详解

【Java编程进阶】抽象类和接口详解

【Java编程进阶】Object类及常用方法详解

在这里插入图片描述

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

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

相关文章

基于Node.js和vue的师生互助平台

摘 要随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&#xff0c;各行各业相继进入信息管理时代&am…

Jetpack Compose中的软键盘与焦点控制

FocusRequester 与 FocusManager 在 Compose 中&#xff0c;可以通过 FocusRequester 与 FocusManager 这两个对象可以主动在代码中控制焦点获取和取消焦点&#xff0c;其中FocusRequester可以用来获取焦点&#xff0c;通过调用它的requestFocus()方法来实现&#xff0c;而 Fo…

脚手架搭建Vue项目

以上创建的方式发现一直存在config目录 换种方式 卸载脚手架命令 npm uninstall vue-cli -g 重新安装 npm install vue/cli -g 1.vue create 项目名 2.模板选择&#xff0c;通过键盘上下键来选择&#xff0c;我们选择第三个 自定义 这三个选择分别是 vue2 / vue3 默认模板…

12.Isaac教程--未来工厂中的搬运车

未来工厂中的搬运车 ISAAC教程合集地址: https://blog.csdn.net/kunhe0512/category_12163211.html 文章目录未来工厂中的搬运车运行模拟器搬运车送货申请自动小车运输的行为树导航与感知互通仅限自主导航申请仅适用于感知训练模型物体检测模型&#xff08;DetectNetv2&#x…

JSP SSM家教管理系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 JSPSSM家教管理系统 是一套完善的系统源码&#xff0c;对理解JSP java SrpingMVC mybiats 框架 MVC编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;以及相应配套的设计文档&#xff0c;系 统主要采用B/S模式开发。 研究的基本内容…

5.5、TCP 的拥塞控制

在某段时间若对网络中某一资源的需求超过了该资源所能提供的可用部分&#xff0c;网络性能就要变坏\color{red}对网络中某一资源的需求超过了该资源所能提供的可用部分&#xff0c;网络性能就要变坏对网络中某一资源的需求超过了该资源所能提供的可用部分&#xff0c;网络性能就…

CSDN第22场周赛

1.写在前面的话22场周赛的详情总比赛第7名了&#xff0c;hhhCSDN周赛非常能够锻炼码代码的能力&#xff0c;无论是在平常的练习题目当中&#xff0c;还是每次的周赛中&#xff0c;题目有难有易&#xff0c;每次周赛的题目出的十分具有代表性&#xff0c;参加了将近20场的周赛&a…

批量PDF文件合并用什么软件?这两个宝藏软件赶快收藏起来

我们在工作中经常有很多处理过的PDF文件&#xff0c;我们经常会将这些文件进行保存&#xff0c;以防日后需要使用&#xff0c;但是太多的PDF文件真的会占用很多存储空间&#xff0c;所以我们可以将各类PDF文件合并在一起&#xff0c;这样也方便以后观看&#xff0c;但是逐个合并…

Docker容器实时日志查看器Dozzle

什么是 Dozzle&#xff1f; Dozzle 是一个小型轻量级应用程序&#xff0c;具有基于 Web 的界面来监控 Docker 日志。Dozzle不存储任何日志文件&#xff0c;仅用于实时监控您的容器日志。 先看个官方的动图 老苏已转成了视频&#xff0c;源文件地址&#xff1a;https://github.c…

制造型企业离不开MES?MES系统有什么应用场景

随着工业物联网的迅速发展&#xff0c;设备监测也成为MES系统中的一个关键环节。过去我们所收集到的资料&#xff0c;也许只是一种记录的作用&#xff0c;随着联网的设备越来越多以及大数据、云计算等技术的发展&#xff0c;数据的价值越来越高。数据收集不再仅仅是一种简单的记…

Codeforces Round #841 (Div. 2) (A--D)

[TOC](Codeforces Round #841 (Div. 2)(A–D)) A、 Joey Takes Money 1、题目 2、思路 3、代码 #include<iostream>#include<algorithm>#include<cstring>using namespace std;typedef unsigned long long ll;int main(){ll t;cin>>t;while(t--){int…

新书赠送丨《中国金融科技发展概览:创新与应用前沿》

我国金融科技发展日新月异&#xff0c;人工智能、云计算、大数据等新兴数字技术与实体经济及金融业的深度融合&#xff0c;推动我国数字经济快速发展&#xff0c;也深刻改变着我国金融业的服务业态和经营模式。过去的一年&#xff0c;金融机构实现核心技术自主可控成为热点&…

影响因子14.65:16S全长测序+低丰度简化菌群,提供根腐病防控新视角

背景介绍当土壤中病原体入侵时&#xff0c;植物可以动态调节其根际微生物并适应这种生物胁迫。植物招募的保护性微生物群落中通常包含一些低丰度的类群&#xff0c;其作用尚不清楚。本研究首先分析了健康和患病黄芪之间根系微生物群落结构的差异&#xff0c;依据患病黄芪根部的…

增加模拟前端的动态范围

1、光电接收电路 下面两张图分别在sensor正偏置和负偏置时的接收电路&#xff0c;这里我们关注一下输出的波形特征为一个脉冲信号&#xff0c;脉冲信号的共模电压为5V分压得到&#xff0c;信号的摆幅为Iout*RT&#xff0c;Iout为光电流&#xff0c;在应用在雷达接收的中时&…

JVM调试命令与调试工具

一、JDK自带命令Sun JDK监控和故障处理命令如&#xff1a;1、jpsJVM Process Status Tool&#xff0c;显示指定系统内所有的HotSpot虚拟机进程。jsp命令格式&#xff1a;jps [ options ] [ hostid ] 扩展参数&#xff1a;jps -l&#xff1b;jps -mlv&#xff1b;各参数说明如下…

tkinter 实现倒计时(1小时)

使用python标准GUI库tkinter实现倒计一小时效果。 废话少说。 效果图&#xff1a; 要不然看个 动态效果 图&#xff1a; 代码&#xff1a; from tkinter import * from tkinter.messagebox import showerrorroot Tk() root.title("倒计时") root.geometry("3…

解析|当前企业OA系统面对的困难与解决方案

近年来&#xff0c;由于疫情爆发&#xff0c;线下的企业办公效率难以保证&#xff0c;不少企业逐渐转向远程办公。尝试过后&#xff0c;远程办公的优势凸显&#xff0c;使得有越来越多的企业开始逐渐深入了解在线办公软件、协同办公OA系统。据统计&#xff0c;2021年数字化办公…

监控docker

当前&#xff0c;容器的使用已经非常普及&#xff0c;将服务迁移到容器上正成为了越来越多公司的选择。而对于运维人员而言&#xff0c;熟悉容器的使用与监控&#xff0c;也已成为一项必不可少的专业技能。关于容器的开源产品&#xff0c;目前知名的有Docker、Containerd、Core…

P2580 于是他错误的点名开始了

题目背景 XS中学化学竞赛组教练是一个酷爱炉石的人。 他会一边搓炉石一边点名以至于有一天他连续点到了某个同学两次&#xff0c;然后正好被路过的校长发现了然后就是一顿欧拉欧拉欧拉&#xff08;详情请见已结束比赛 CON900&#xff09;。 题目描述 这之后校长任命你为特派探员…

范数的意义与计算方法(使用NumPy)

1. 范数的意义 范数可以简单的理解为“距离”。由于向量是既有大小又有方向的量&#xff0c;所以向量是不能直接比较大小的&#xff0c;但是范数提供了一种方法&#xff0c;可以将所有的向量转化为一个实数&#xff0c;然后就可以比较向量的大小了。&#xff08;注&#xff1a…