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

Java—— 异常详解

异常是什么

程序中可能出现的问题

例如:

int[] arr1 = {1,2,3}; System.out.println(arr1[10]); 会出现索引越界异常

String[] arr2 = new String[10]; System.out.println(arr2[0].equals("a")); 会出现空指针异常

异常的继承体系 

Error: 代表的系统级别错误(属于严重问题)
系统一旦出现问题,sun公司会把这些错误封装成Error对象。
Error是给sun公司自己用的,不是给我们程序员用的。
因此我们开发人员不用管它。 

Exception: 叫做异常,代表程序可能出现的问题。
我们通常会用Exception以及他的子类来封装程序出现的问题。
运行时异常:RuntimeException及其子类,编译阶段不会出现异常提醒。运行时出现的异常(如:数组索引越界异常),一般是由于参数传递错误带来的问题
编译时异常:编译阶段就会出现异常提醒的。(如:日期解析异常) ,作用在于提醒程序员

异常的作用

1.异常是用来查询bug的关键参考信息
2.异常可以作为方法内部的一种特殊返回值,以便通知调用者底层的执行情况

异常的处理

JVM默认处理异常的方式

1.把异常的名称,异常原因及异常出现的位置等信息输出在了控制台
2.程序停止执行,异常下面的代码不会再执行了

代码演示
package demo7;public class Test1 {public static void main(String[] args) {System.out.println("第一句打印语句以执行");System.out.println("第二句打印语句以执行");System.out.println(2 / 0);System.out.println("第三句打印语句以执行");System.out.println("第四句打印语句以执行");//控制台结果为://第一句打印语句以执行//第二句打印语句以执行//Exception in thread "main" java.lang.ArithmeticException: / by zero//at demo7.Test1.main(Test1.java:10)}
}

自己处理(捕获异常)

格式:
try{
        可能出现异常的代码;
} catch(异常类名 变量名){
        异常的处理代码;
}

目的:当代码出现异常时,可以让程序继续往下执行。 

代码演示
public class Test2 {public static void main(String[] args) {int[] arr = {1, 2, 3};try {System.out.println(arr[10]);//此处出现了异常,程序就会在这里创建一个ArrayIndexOutOfBoundsException对象//new ArrayIndexOutOfBoundsException();//拿着这个对象到catch的小括号中对比,看括号中的变量是否可以接收这个对象//如果能被接收,就表示该异常就被捕获(抓住),执行catch里面对应的代码//当catch里面所有的代码执行完毕,继续执行try...catch体系下面的其他代码} catch (ArrayIndexOutOfBoundsException e) {System.out.println("索引越界异常");}System.out.println("看看我执行了没有");//控制台结果为://索引越界异常//看看我执行了没有}
}
关于捕获异常的四个问题

如果try中没有遇到异常,怎么执行?

会执行try中的所有代码,不会执行catch中的代码

public class Test3 {public static void main(String[] args) {int[] arr = {1, 2, 3};try {System.out.println(arr[0]);System.out.println(arr[1]);System.out.println(arr[2]);System.out.println(2 / 1);} catch (RuntimeException e) {System.out.println("存在异常");}System.out.println("看看我执行了吗");//控制台结果为://1//2//3//2//看看我执行了吗}
}

如果try中可能会遇到多个异常,怎么执行?

会写多个catch与多个可能出现的异常对应
细节:

1. try中遇见有异常的语句,会跳转到与之对应的catch中执行catch中的语句,try中的异常语句下面的语句将会被跳过不执行,不管是否还有异常语句
2. 如果我们要捕获多个异常,这些异常中如果存在父子关系的话,那么父类一定要写在下面
3. 在JDK7之后,我们可以在catch中同时捕获多个异常,中间用|进行隔开表示如果出现了A异常或者B异常的话,采取同一种处理方案

public class Test4 {public static void main(String[] args) {int[] arr1 = {1, 2, 3};String[] arr2 = new String[10];try {System.out.println(arr2[1].equals("a"));System.out.println(arr1[10]);System.out.println(2 / 0);} catch (ArrayIndexOutOfBoundsException e) {System.out.println("存在异常");} catch (ArithmeticException | NullPointerException e) {System.out.println("存在算数异常或空指针异常");} catch (RuntimeException e) {System.out.println("存在异常");}System.out.println("看看我执行了吗");//控制台结果为://存在算数异常或空指针异常//看看我执行了吗}
}

如果try中遇到的问题没有被捕获,怎么执行?

相当于try...catch白写了,当前异常会交给虚拟机处理

如果try中遇到了问题,那么try下面的其他代码还会执行吗?

不会执行了。try中遇到问题,直接跳转到对应的catch

如果没有对应的catch与之匹配,则交给虚拟机处理

Throwable 的成员方法
方法名称说明
public string getMessage()返回异常的描述
public String toString()返回异常的名字和描述
public void printStackTrace()在底层是利用System.err.println进行输出
把异常的错误信息以红色字体输出在控制台
细节:仅仅是打印信息,不会停止程序运行
public class Test5 {public static void main(String[] args) {int[] arr = {1, 2, 3};try {System.out.println(arr[10]);} catch (ArrayIndexOutOfBoundsException e) {String str1 = e.getMessage();System.out.println(str1);//Index 10 out of bounds for length 3String str2 = e.toString();System.out.println(str2);//java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 3e.printStackTrace();//java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 3//      at demo7.Test5.main(Test5.java:13)}System.out.println("看看我执行了吗");//看看我执行了吗}
}

抛出处理

说明

在方法中,出现异常了。
方法就没有继续运行下去的意义了,采取抛出处理。
让该方法结束运行并告诉调用者出现了问题。

关键字throws

写在方法定义处,表示声明一个异常,告诉调用者,使用本方法可能会有哪些异常
public void 方法() throws 异常类名1,异常类名2...{

        ...
}

注意:
编译时异常:必须要写。
运行时异常:可以不写。

关键字throw

写在方法内,结束方法,手动抛出异常对象交给调用者,方法中下面的代码不再执行了
public void 方法(){
        throw new 异常名();

}

代码演示

定义一个方法,查找一个数组中的最大值

public class Test6 {public static void main(String[] args) {//定义一个方法,查找一个数组中的最大值int[] arr = null;int max;try {max = getMax(arr);System.out.println(max);} catch (NullPointerException e) {e.printStackTrace();} catch (ArrayIndexOutOfBoundsException e) {e.printStackTrace();}System.out.println("看看我执行了吗");//看看我执行了吗}public static int getMax(int[] arr) /*throws NullPointerException,ArrayIndexOutOfBoundsException*/ {if (arr == null) {throw new NullPointerException();}if (arr.length == 0) {throw new ArrayIndexOutOfBoundsException();}int max = arr[0];for (int i = 0; i < arr.length; i++) {if (arr[i] > max) {max = arr[i];}}return max;}
}

自定义异常

说明

如果java中已经定义好的异常无法满足自己的需要,我们可以自定义异常

步骤

1.定义异常类
2.写继承关系

        运行时异常就继承RuntimeException,编译时异常继承Exception
3.空参构造
4.带参构造

意义

就是为了让控制台的报错信息更加的见名之意

练习

键盘录入数据
需求:
键盘录入学生姓名和年龄。
姓名的长度在2-4之间,
年龄的范围为18-40岁,
超出这个范围是异常数据不能赋值,需要重新录入,一直录到正确为止。
提示:
需要考虑用户在键盘录入时的所有情况。
比如:录入年龄时超出范围,录入年龄时录入了abc等情况 

自定义姓名格式异常

//自定义姓名格式异常,运行时异常
public class NameFormatException extends RuntimeException {//空参构造public NameFormatException() {}//带参构造public NameFormatException(String message) {super(message);}
}

自定义年龄越界异常 

//自定义年龄越界异常,运行时异常
public class AgeOutOfBoundsException extends RuntimeException {//空参构造public AgeOutOfBoundsException() {}//带参构造public AgeOutOfBoundsException(String message) {super(message);}
}

Student类 

public class Student {private String name;private int age;public Student() {}public Student(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public int getAge() {return age;}//设定姓名时进行判断public void setName(String name) {if (name.length() < 2 || name.length() > 4) {//报姓名格式异常throw new NameFormatException("姓名" + name + "的字数不在2-4之间");}this.name = name;}//设定年龄时进行判断public void setAge(int age) {if (age < 18 || age > 40) {//报年龄越界异常throw new AgeOutOfBoundsException("年龄" + age + "的范围不在18-40岁之间");}this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}

测试类

import java.util.Scanner;public class Test {public static void main(String[] args) {Scanner sc = new Scanner(System.in);Student s = new Student();while (true) {try {System.out.println("请输入姓名");String name = sc.nextLine();s.setName(name);System.out.println("请输入年龄");String ageStr = sc.nextLine();int age = Integer.parseInt(ageStr);s.setAge(age);//到这一步,证明上述语句没有异常//否则跳转到catch,跳过break进行循环break;} catch (NumberFormatException e) {//数字格式异常,转换的字符串不是纯数字e.printStackTrace();} catch (NameFormatException e) {//姓名格式异常e.printStackTrace();} catch (AgeOutOfBoundsException e) {//年龄越界异常e.printStackTrace();}}System.out.println(s);}
}
http://www.xdnf.cn/news/507313.html

相关文章:

  • Python训练营打卡Day28(2025.5.17)
  • 芯片生态链深度解析(三):芯片设计篇——数字文明的造物主战争
  • 实例化异常(InstantiationException)详解
  • Python高版本降低低版本导致python导包异常的问题
  • 打卡Day28
  • CAS(Compare-And-Swap)详解
  • c++ 友元函数
  • STM32入门笔记(06):STM32Cube 生态系统 (STM32CubeMX图形工具STM32CubeIDE 集成开发环境)(HAL库)
  • W5500使用ioLibrary库创建DHCP客户端
  • Day12-苍穹外卖(完结篇)
  • Typecho博客为文章添加AI摘要功能(Handsome主题优化版)
  • 江协科技OLED移植hal库
  • 院校机试刷题第五天:1912循环位移、1913礼炮车
  • CE17.【C++ Cont】练习题组17(堆专题)
  • 基于C++11CAS实现无锁队列
  • 【IP101】图像“瘦身魔法“详解:从基础细化到Zhang-Suen、Hilditch算法与中轴变换的完整代码实现
  • 剖析智能指针shared_ptr实现原理
  • Devin 编程智能体
  • 2023 睿抗机器人开发者大赛CAIP-编程技能赛-专科组(国赛)解题报告 | 珂学家
  • Active Directory域环境信息收集实战指南
  • 摄影构图小节
  • [逆向工程]C++实现DLL注入:原理、实现与防御全解析(二十五)
  • Flowbite 和 daisyUI 那个好用?
  • AI Agent开发第69课-彻底消除RAG知识库幻觉(3)-手撕“重排序”
  • W5500使用ioLibrary库创建DNS客户端
  • 【人工智能】DeepSeek解码:揭秘AI大模型训练的创新密码
  • 从0到1:Python项目部署与运维全攻略(10/10)
  • 如何在Cursor中高效使用MCP协议
  • 桌面端进程通信
  • 第十一课 蜗牛爬树