网站首页 > java教程 正文
文章目录
1 异常引入
2 异常简介
2.1 异常的概念
2.2 常见异常体系图
3 常见运行时异常举例
3.1 NullPointerException
3.2 ArrayIndexOutOfBoundsException
3.3 ClassCastException
3.4 NumberFormatException
4 异常处理
4.1 try-catch-finally 异常处理
4.2 try - catch练习题(坑)
4.2.1 阅读程序
4.2.2 输入校验
4.3 throws 异常处理
4.4 自定义异常
4.4.1 自定义异常实例
4.5 throw 和 throws 的区别
5 编程练习
写在最后
1 异常引入
不知道初学Java 时,大家是不是和博主一样一脸懵:“这异常到底是个什么东东,有什么用嘞?” 今天,咱们就专门来展开讲讲异常。
还是那个教科书里面的标准例子,来看一下吧:
在例子中,我们将 0 作为除数进行运算,运行结果如下:
程序控制台好像出现了不得了的东西!细细一看,原来是告诉我们出现了算术异常。不过只要再细心看一下代码,你就会发现:程序并没有执行完成,因为控制台并没有输出“程序运行结束标记”这句话!而是在计算 res 的时候,就中断了。 这就导致了一个很严重的问题:在我们实际开发中,一个完整的项目,文件可能都多达上千个,难道可以因为这样的小错误就直接崩溃,停止运行吗?
答案是否定的,因此, 我们需要使用异常处理机制,来提升项目的健壮性!
在idea编译器中,我们可以先选中代码块,然后使用快捷键 ctrl + alt + t 在弹出的二级菜单中,一键添加 try - catch ,(偷懒小技巧增加了~~~)
来看一下添加异常机制后,程序的运行情况吧!
代码如下:
运行结果:
虽然运行结果同样抛出了异常信息,但是,程序并没有因此而中止!而是继续向后执行,结束标记输出就是最好的证明~
怎么样?现在是不是就对异常有兴趣啦!来,进入正题,我们慢慢聊~
2 异常简介
2.1 异常的概念
在 Java 中,异常即为程序执行过程中发生的不正常情况。 但是需要注意的是,程序员在编码过程中的逻辑与语法错误不属于异常的范畴!
程序执行过程中所发生的异常可以分为如下两大类:
1?? Error: Java 虚拟机无法解决的严重问题。如: JVM系统内部错误、资源耗尽等。举例:栈溢出(StackOverflowError)
2?? Exception: 其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。分为两大类:
运行时异常: 又叫非受检异常,即程序运行时,发生的异常;
编译时异常: 又叫受检异常,即编程时,编译器检查出的异常。
图示如下:
助记:
编译时异常: 编译器检查出来的异常,必须处理,不然运行不了;
运行时异常: 编译器没有检查出来,程序可以跑,可以 选择性处理。
2.2 常见异常体系图
Java把异常当作对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类。在Java API中已经定义了许多异常类,这些异常类分为两大类,错误Error和异常Exception。Java异常体系结构呈树状,常见异常的层次结构图如图所示:
Throwable 实现了 Serializable 接口。向下分为 Error 与 Exception。而 Exception 我们可以通过异常处理机制来解决。我们着重处理 RuntimeException 即 运行时异常,其常见的子类如下,上面的图可能看不清,我们来放大看:
3 常见运行时异常举例
3.1 NullPointerException
空指针异常,当应用程序在需要对象的地方使用null时,抛出该异常。
示例代码:
public class NullPointerException {
public static void main(String[] args) {
String s = null;
System.out.println(s.length());
}
}
结果:
Exception in thread “main” java.lang.NullPointerException: Cannot invoke “String.length()” because “s” is null
at exception.NullPointerException.main(NullPointerException.java:10)
3.2 ArrayIndexOutOfBoundsException
数组下标越界异常。 用非法索引访问数组时抛出该异常,即数组越界。
示例代码:
public class ArrayIndexOutOfBoundsException {
public static void main(String[] args) {
int[] arr = {1, 2, 3};
System.out.println(arr[3]); // 越界
}
}
1
2
3
4
5
6
结果:
Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
at exception.ArrayIndexOutOfBoundsException.main(ArrayIndexOutOfBoundsException.java:10)
3.3 ClassCastException
类型转换异常。当试图将一个对象强制转换为不是实例的子类时,抛出该异常。
示例代码:
public class ClassCastException {
public static void main(String[] args) {
Animal dog = new Dog();
Dog d = (Dog)dog; // 向下转型
Cat c = (Cat)dog; // 该句错误!!!!
}
}
class Animal{}
class Dog extends Animal{}
class Cat extends Animal{}
1
2
3
4
5
6
7
8
9
10
结果:
Exception in thread “main” java.lang.ClassCastException: class exception.Dog cannot be cast to class exception.Cat (exception.Dog and exception.Cat are in unnamed module of loader ‘app’)
at exception.ClassCastException.main(ClassCastException.java:11)
3.4 NumberFormatException
数字格式异常。当应用程序试图将字符串转成一种数值类型,但字符串不能转换为适当格式时,抛出该异常。 使用异常我们可以确保输入满足条件的数字。
示例代码:
public class NumberFormatException {
public static void main(String[] args) {
int num = Integer.parseInt("123.456"); // 转不了
}
}
1
2
3
4
5
结果:
Exception in thread “main” java.lang.NumberFormatException: For input string: “123.456”
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:68)
at java.base/java.lang.Integer.parseInt(Integer.java:652)
at java.base/java.lang.Integer.parseInt(Integer.java:770)
at exception.NumberFormatException.main(NumberFormatException.java:9)
4 异常处理
异常处理即当异常发生时,对异常处理的方式。 主要有两种处理方式:
try-catch-finally:程序员在代码中自行处理,捕获异常;
throws:将异常抛出,交给调用者(方法)来处理,最顶级的处理者就是JVM。示意图如下:
main方法如果没有进行 try catch,默认会进行 throws。
4.1 try-catch-finally 异常处理
Java 提供 try 和 catch 块来处理异常。try 块用于包含可能出错的代码,catch 块用于处理 try 块发生的异常。finally 块可选择性添加,用于执行始终需要执行的代码。
? 基本语法:
try{
// 可能发生异常的代码
// 将异常生成对应的异常对象,传递给 catch 块
}catch(异常){
// 对异常的处理
}finally{
// 不管 try 是否有异常,始终都要执行 finally 块的代码
// 通常将需要释放资源的代码放在 finally
}
1
2
3
4
5
6
7
8
9
使用细节:
1?? 如果异常发生了,则异常后面的代码不会执行,直接进入到 catch 块。
如果异常没有发生,则顺序执行 try 代码块,不会进入 catch 块。
如果 try 代码块有多个异常,可以使用多个 catch 分别捕获并进行相应的处理。 但是要求 子类必须在父类前面! 值得注意的是,异常捕获的时候,当捕获到第一个,后面的将不再捕获。
允许使用 try - finally ,但是这种做法相当于没有捕获异常,finally
相当于进行了善后处理, 即 程序还是会因为异常中断,但是会执行该代码块中的代码后再中断(垂死挣扎)
4.2 try - catch练习题(坑)
4.2.1 阅读程序
请阅读下面代码,猜猜输出结果:
public class Exception01 {
public static int method(){
int i = 1;
try {
i++;
String[] name = new String[3];
if(name[1].equals("ABC")){ // 发生了空指针异常
System.out.println("ABC");
}
}catch (NullPointerException e){
return ++i;
}finally {
++i;
System.out.println("i = " + i);
}
return 0;
}
public static void main(String[] args) {
System.out.println(method());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
结果:
i = 4
3
解析:在 if 语句中发生了空指针异常,try 块其余代码不执行。执行 catch 块代码,此时应该 return 3。但是由于 finally 块一定要被执行,因此,程序会先将 return 的 i 值暂时存储起来,去执行 finally 块的代码。所以先输出 i = 4 后返回3.
4.2.2 输入校验
题目要求:
请你编写一段程序,用于判断用户的输入:如果输入不是整数,就提示错误信息,直到输入正确为止。
思路分析:
创建 Scanner 对象;
使用循环去接收一个输入;
将该输入尝试转换成 int;
如果转换时发生异常,说明输入有误,不能转换;
如果没有抛出异常,则输入正确,提示即可。
参考代码:
public class TryCatch {
public static void method() {
Scanner scanner = new Scanner(System.in);
int num = 0;
while (true) {
System.out.println("请输入一个整数: ");
try {
num = Integer.parseInt(scanner.next()); // 有可能抛出异常
break; // 没有抛出则退出循环
} catch (NumberFormatException e) {
System.out.println("你输入的不是整数, 请重新输入!");
}
}
System.out.println("输入正确!");
}
public static void main(String[] args) {
method();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
实验结果:
4.3 throws 异常处理
基本介绍:
如果一个方法可能生成某种异常,但是 并不确定如何处理这些异常,则该方法应显式地声明抛出异常 ,表明该方法将不对这些异常进行处理,而由该方法的调用者负责处理。在方法声明中抛出异常的列表,throws 后面的异常类型可以是方法中产生的异常类型,也可以是它的父类。
? 基本语法:
方法名 throws 异常类1, 异常类2......{
// 方法体
}
1
2
3
使用细节:
1?? 对于运行时异常,程序如果没有处理,默认就是 throws 的方式处理;
2?? 子类重写父类的方法时,对抛出异常有一条规定:子类重写的方法,所抛出的异常类型要么与父类抛出的异常一致,要么为父类抛出的异常类型的子类型; 演示如下:
4.4 自定义异常
当程序出现了某些错误,但该错误信息并没有在 Throwable 子类中描述处理,这个时候可以自己设计异常类,用于描述该错误信息。
自定义异常的步骤:
1.定义类:自定义异常类名,继承 Exception 或者 RuntimeException;
2. 如果继承了 Exception,属于编译异常;
3.如果继承了 RuntimeException,属于运行异常。
4.4.1 自定义异常实例
来看一个需求:
当接收 Person 对象年龄时,要求范围在 18~120 之间,否则抛出自定义异常,并给出提示信息。(要求继承 RuntimeException)
? 参考代码:
public class Main {
public static void main(String[] args) {
Person person = new Person(125); // 设置年龄125 出现了异常
}
}
class Person{
private int age;
public Person(int age){
this.age = age;
ageException();
}
// 判断异常
public void ageException(){
if(!(age >= 18 && age <= 120)){
throw new AgeException("年龄需要在18 ~ 120之间");
}
System.out.println("范围正常");
}
}
// 自定义异常
class AgeException extends RuntimeException{
public AgeException(String message){
super(message);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
结果:
4.5 throw 和 throws 的区别
区别一览表:
5 编程练习
题目描述(题目摘自 bilibili 韩顺平 Java 课程 P456):
编写程序接收两个参数(整数),计算两数相除。要求使用方法 cal(int num1, int num2)。对于数据格式不正确(NumberformatException)、缺少命令行参数(ArrayIndexOutOfBoundsException)、除0进行异常处理(ArithmeticException)。
参考代码:
public class Main {
public static void main(String[] args) {
// 先检验输入参数的个数
try {
if(args.length != 2){
throw new ArrayIndexOutOfBoundsException("参数个数不对");
}
// 把接收到的参数转成整数
int n1 = Integer.parseInt(args[0]);
int n2 = Integer.parseInt(args[1]);
double res = cal(n1, n2); // 可能算数异常
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println(e.getMessage());
} catch (NumberFormatException e){
System.out.println("参数格式不正确");
} catch (ArithmeticException e) {
System.out.println("算术异常,0不能做除数");
}
}
// 编写方法,计算
public static double cal(int n1, int n2){
return n1/n2;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
输入(配置如下图,注意用空格分隔):
结果:
算术异常,0不能做除数
总结了很多有关于java面试的资料,希望能够帮助正在学习java的小伙伴。由于资料过多不便发表文章,创作不易,望小伙伴们能够给我一些动力继续创建更好的java类学习资料文章,
请多多支持和关注小作,别忘了点赞+评论+转发。右上角私信我回复【03】即可领取免费学习资料谢谢啦!
原文出处:https://blog.csdn.net/m0_60353039/article/details/124697705?spm=1001.2100.3001.7377&utm_medium=distribute.pc_feed_blog_category.none-task-blog-classify_tag-2-124697705-null-null.nonecase&depth_1-utm_source=distribute.pc_feed_blog_category.none-task-blog-classify_tag-2-124697705-null-null.nonecase
猜你喜欢
- 2024-09-16 php还是java,选择比努力更重要!(php和java一样吗)
- 2024-09-16 我知道了我成绩差的原因,看完一定会有收获
- 2024-09-16 学计算机,学编程我劝你不要太老实!!
- 2024-09-16 假如从5月开始学Java(从五月份学习到现在)
- 2024-09-16 我恨计算机,但我永远感激自己选择了它
- 2024-09-16 机械转码的学习流程(机器转换)
- 2024-09-16 学习编程需不需要背代码呢?(学编程要刷题吗)
- 2024-09-16 希望计算机专业同学都知道这些老师
- 2024-09-16 2020最新版Java学习路线图-110G视频教程
- 2024-09-16 尚硅谷Java数据结构与算法、设计模式教程双双发布
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)