前言:异常处理是 java 编程中非常重要的一部分,它能够有效地捕获和处理程序运行中的错误,提高代码的健壮性和可靠性。本文将深入探讨 java 中异常的概念、体系结构、抛出、解决方式以及如何自定义异常,并结合代码案例进行详细解释。
先让我们看一下本文的大致内容:
目录
1. nullpointerexception(空指针异常)
2. arrayindexoutofboundsexception(数组越界异常)
1.异常的概念
——在学习java中的异常之前,先让我们了解一下什么是java中的异常:
相信读者在日常的编写代码的时候,或多或少的都遇到过一些异常,只是读者你可能没有太注意它们,比如如下异常:
1. nullpointerexception(空指针异常)
空指针异常通常发生在尝试访问对象的属性或调用对象的方法时,而该对象为 null 的情况下。
public class nullpointerexceptionexample {
public static void main(string[] args) {
string str = null;
system.out.println(str.length()); // 这行代码会抛出 nullpointerexception
}
}
2. arrayindexoutofboundsexception(数组越界异常)
数组越界异常发生在尝试访问数组的不存在的索引位置时。
public class arrayindexoutofboundsexceptionexample {
public static void main(string[] args) {
int[] arr = new int[3];
system.out.println(arr[5]); // 这行代码会抛出 arrayindexoutofboundsexception
}
}
3. arithmeticexception(算术异常)
算术异常发生在进行除以零的算术运算时。
public class arithmeticexceptionexample {
public static void main(string[] args) {
int a = 10;
int b = 0;
system.out.println(a / b); // 这行代码会抛出 arithmeticexception
}
}
当然,这以上只是举出来几个常见的异常的案例,所以我们就可以知道了异常类型和如何处理它们对于编写健壮的 java 代码非常重要。
2.异常的体系结构
(1)异常的体系结构
在java中,java 异常体系结构是由一组类构成的,它们都是 throwable
类的子类。常见的异常类包括 error
、runtimeexception
以及它们的子类。error
类及其子类通常表示严重的错误,如系统错误或虚拟机错误,程序通常无法恢复。runtimeexception
及其子类通常表示程序逻辑错误或运行时错误,如空指针异常、数组越界异常等。
我们可以直接看一下以下这幅图进行理解:
从上图中可以看到:
(2)异常的分类
在java中,异常可能在编译时发生,也可能在程序运行时发生,根据发生的时机不同,可以将异常分为两类:
1.编译时异常:
import java.io.file;
import java.io.filereader;
import java.io.filenotfoundexception;
public class compiletimeexceptionexample {
public static void main(string[] args) {
try {
file file = new file("nonexistent_file.txt"); // 这里假设文件不存在
filereader fr = new filereader(file); // 可能抛出 filenotfoundexception
} catch (filenotfoundexception e) {
system.out.println("文件未找到异常:" + e.getmessage());
}
}
}
注意:
2.运行时异常:
public class runtimeexceptionexample {
public static void main(string[] args) {
int[] array = {1, 2, 3};
try {
system.out.println(array[5]); // 可能抛出 arrayindexoutofboundsexception
} catch (arrayindexoutofboundsexception e) {
system.out.println("数组越界异常:" + e.getmessage());
}
}
}
这样我们就大致的了解了异常的体系结构了。
3.异常的抛出
当然,在编写程序时,如果程序中出现错误,此时就需要将错误的信息告知给调用者,比如:参数检测。在java中,可以借助throw关键字,抛出一个指定的异常对象,将错误信息告知给调用者。具体语法如下:
throw new xxxexception("异常产生的原因");
让我们看一下一个案例:
public static void validateage(int age) {
if (age < 18) {
//异常的抛出
throw new invalidageexception("未满18岁,不允许访问。");
}
system.out.println("年龄验证通过。");
}
【注意事项】
这样我们就大致的了解了如果有异常之后,我们如果将其进行抛出了。但是异常是抛出了,那我们如何去解决抛出的异常呢?
4.异常的解决方式
——在java中异常的具体处理方式主要有两种:异常声明 throws 以及 try-catch捕获处理。
(1)异常声明throws
当方法中抛出编译时异常,用户不想处理该异常,此时就可以借助throws将异常抛给方法的调用者来处理。即当前方法不处理异常,提醒方法的调用者处理异常。
其语法形式为:
修饰符 返回值类型 方法名(参数列表) throws 异常类型1,异常类型2...{
}
让我们直接使用一个案例来进一步帮助你进行理解:
public static void divide(int a, int b) throws arithmeticexception {
if (b == 0) {
throw new arithmeticexception("除数不能为0");
}
int result = a / b;
system.out.println("结果:" + result);
}
我们可以在这个案例中看到,如果b == 0时,我们抛出了异常,但是我们并没有在此方法中对该异常进行处理,而是将其继续抛出,给调用者处理。这就是第一种处理异常的方式throws。
【注意事项】
(2)使用try - catch - finally语句
——在java中,异常可以通过try-catch-finally语句块来进行处理。由于throws对异常并没有真正处理,而是将异常报告给抛出异常方法的调用者,由调用者处理。如果真正要对异常进行处理,就需要try-catch。
其基本语法为:
try {
// 可能抛出异常的代码
} catch (exceptiontype1 e1) {
// 处理异常类型1的情况
} catch (exceptiontype2 e2) {
// 处理异常类型2的情况
} finally {
// 可选的finally语句块,用于执行清理操作
}
在try语句块中,我们可以放置可能抛出异常的代码。如果try语句块中的代码抛出了异常,那么异常会被catch语句块捕获。catch语句块中的参数指定了要捕获的异常类型,当抛出的异常与catch语句块中指定的类型匹配时,相应的catch语句块会被执行。如果try语句块中的代码未抛出异常,则catch语句块会被跳过。
另外,finally语句块是可选的,用于执行清理操作,无论是否发生异常都会执行。finally语句块通常用于释放资源或执行必要的收尾工作,例如关闭文件或数据库连接。
这里我们使用一个案例来帮助你进一步理解:
public class simpleexceptionhandlingexample {
public static void main(string[] args) {
int a = 10;
int b = 0;
int result = 0;
try {
// 尝试进行除法运算
result = a / b;
system.out.println("除法运算结果:" + result);
} catch (arithmeticexception e) {
// 捕获除零异常并输出错误信息
system.err.println("除法运算出错:除数不能为零");
} finally {
// 无论是否发生异常,都会执行的代码块
system.out.println("finally块:结束异常处理");
}
}
}
首先我们对10除以0进行除法运算。由于除数为0,会抛出arithmeticexception异常。我们在try块中捕获这个异常,并输出错误信息。无论是否发生异常,finally块中的代码都会执行,这里我们简单输出一条结束异常处理的消息。
【注意事项】
这里我们对第四条加以解释:如果多个异常的处理方式是完全相同,我们可以使用“ | ”隔开
例如:
catch (arrayindexoutofboundsexception | nullpointerexception e) {
//对异常进行处理的代码
}
——当然我们可以一直 | 添加异常,但是实际上不建议使用这样的方式处理,因为这样处理我们将不知道到底try中代码出现了什么类型的异常 (比如上面的代码可能出现的异常类型为arrayindexoutofboundsexception ,也可能是 nullpointerexception异常类型)
这样我们就大致的了解了java处理异常的两种方式了。
补充:异常处理流程总结
5.自定义异常
说到自定义异常,我们首先要了解一下什么是自定义异常:
了解完了什么是自定义异常之后,先让我们看一下如何去创建一个自定义异常。
创建一个自定义异常类,方式如下:
例子:
// 自定义运行时异常类
class invalidageexception extends runtimeexception {
// 无参构造方法
public invalidageexception() {
super("年龄无效");
}
// 带有异常消息的构造方法
public invalidageexception(string message) {
super(message);
}
}
这样我们就创建好了一个自定义异常了,那么自定义异常创建好之后,我们又该如何的使用它呢?让我们继续往下看!
现在我们将要使用刚才创建好的自定义异常类来完成一个小案例:(代码如下)
// 创建人类
class person {
private string name;
private int age;
// 构造方法
public person(string name, int age) {
this.name = name;
// 检查年龄是否有效,如果无效则抛出自定义异常
if (age < 0 || age > 150) {
//使用了我们刚才创建的自定义异常类
throw new invalidageexception("年龄必须在0到150之间");
}
this.age = age;
}
// 获取年龄
public int getage() {
return age;
}
}
//测试类
public class customruntimeexceptionexample {
public static void main(string[] args) {
// 创建一个人类对象,年龄为负数,会抛出自定义异常
try {
person person = new person("alice", -10);
system.out.println(person.getage());
} catch (invalidageexception e) {
// 捕获并处理自定义异常
system.err.println("创建人物失败:" + e.getmessage());
}
// 创建一个人类对象,年龄超过有效范围,也会抛出自定义异常
try {
person person = new person("bob", 160);
system.out.println(person.getage());
} catch (invalidageexception e) {
// 捕获并处理自定义异常
system.err.println("创建人物失败:" + e.getmessage());
}
}
}
在上面的代码中,我们首先定义了一个名为invalidageexception的自定义异常类,它继承自runtimeexception类。然后我们定义了一个person类,其中包含一个构造方法用于创建人类对象,并在构造方法中检查年龄是否有效。如果年龄无效,则抛出invalidageexception异常。
然后在main方法中,我们分别创建了两个person对象,一个年龄为负数,一个年龄超过有效范围。在创建这两个对象时,都会抛出自定义异常。我们使用try-catch语句块捕获并处理这些异常,输出错误信息到控制台。
通过这个案例我相信读者你已经大致的了解了如何创建一个自定义异常类和如何去使用创建的自定义异常类了。
注意事项:
这样我们就了解了java中自定义异常了。
以上就是本篇文章的所以内容了~~~
发表评论