目录
一、异常
Java语言中,将程序执行中发生的不正常情况称为“异常”
Error
Java虚拟机无法解决的严重问题(Error是严重错误,程序会崩溃)
如:JVM系统内部错误、资源耗尽等严重情况
比如:StackOverflowEeeor[栈溢出]、OOM(out of memory)
Exception
其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理
例如:空指针访问、试读不存在的文件、网络连接中断
- 运行时异常:程序运行时,发生的异常
- 编译时异常:编程时,编译器检查出的异常
二、异常体系图
- 异常分为两大类,运行时异常和编译时异常
- 运行时异常:编译器一般检查不出来,一般是指编程时的逻辑错误,是程序员应该避免其出现的异常
- 对于运行时异常,可以不做处理,因为这类异常很普遍,若全处理可能影响对程序的可读性和运行效率
- 编译时异常:是编译器要求必须处置的异常
三、运行时异常
NumberFormatException
空指针异常
String name = "zhou";
// String name = null; //⚠️
System.out.println(name.length());
ArithmeticException
数学运算异常
//(2)数学运算异常
System.out.println(1 / 1);
// System.out.println(1 / 0); //⚠️
ArrayIndexOutOfBoundsException
数组下标越界异常
//(3)数组下标越界异常
int[] arr = new int[4];
System.out.println(arr[3]);
// System.out.println(arr[4]); //⚠️
ClassCastException
类型转换异常
//(4)类型转换异常
A a = new B();
B b = (B)a;
// C c = (C)a; //⚠️
NumberFormatException
数学格式不正确异常
//(5)数字格式不正常异常
String num = "123";
// String num = "zhou"; //⚠️
System.out.println(Integer.parseInt(num));
四、编译时异常
- SQLException :操作数据库时,查询表可能发生异常
- IOException :操作文件时,发生的异常
- FileNotFoundException :当操作一个不存在的文件时,发生异常
- ClassNotFoundException :加载类,而该类不存在
- EOFException :操作文件,到文件末尾,发生异常
- IIIegalArguementException :参数异常
五、异常处理
异常处理就是当异常发生时,对异常处理的方式
try- catch-finally
程序员在代码中捕获发生的异常,自行处理
try{
代码(可能有异常)
}
catch(Exception e){
---(捕获到异常)
---当异常发生时 //1⃣️
---系统将异常封装成Exception对象e,传递给catch //2⃣️
---得到异常对象后,程序员自己处理 //3⃣️
---如果没有异常,catch代码块不执行 //4⃣️
}
finally{
---不管try代码块是否有异常发生,始终要执行finally//1⃣️
---通常将释放资源的代码放在finally //2⃣️
}
thorws
将发生的异常抛出,交给调用者来处理,最顶级的处理者是JVM
六、try- catch-finally异常处理
1. 基本介绍
Java提供try和catch块来处理异常,try块用于包含可能出错的代码,catch块用于处理try块中发生的异常
package Java.Exception;
import java.util.Scanner;
/**
* @author 鹿青舟
* @version 1.0
*/
public class TryCatchExercise {
public static void main(String[] args) {
Boolean bool;
System.out.println("请输入一个整数:");
do {
bool = false;
try {
Scanner scanner = new Scanner(System.in);
String num = scanner.next();
Integer.parseInt(num);
System.out.println("输入正确");
} catch (NumberFormatException e) {
System.out.println("输入的不是整数,请重新输入:");
bool = true;
}
} while (bool);
System.out.println("程序继续");
}
}
2. 注意示例
- 如果异常发生了,则异常发生后面的代码不会执行,直接进入到catch块
- 如果异常没有发生,则顺序执行try的代码块,不会进入catch
- 如果希望不管是否发生异常,都执行某段代码(比如关闭连接,释放资源)
- 可以有多个catch语句,捕捉不同的异常(进行不同的业务处理),要求父类异常在后,子类异常在前,比如(Exception在后,NullPointerException在前),如果发生异常,只会匹配一个catch
- 可以进行try-finally配合使用,这种用法相当于没有捕获异常,因此程序会直接崩掉/退出。
try{
//可疑代码
}catch(异常){
//...
}catch(异常){
//...
}finally{
//释放资源等
}
package Java.Exception;
/**
* @author 鹿青舟
* @version 1.0
*/
public class Try_catch_finally {
public static void main(String[] args) {
//1⃣️try代码块有可能有多个异常
//2⃣️可以使用多个catch分别捕获不同的异常,分类处理
//3⃣️要求子类异常写在前面,父类异常写在后面
try {
Person person = new Person("Tom");
person = null;
System.out.println(person.name);
System.out.println("------");
int n1 = 1;
int n2 = 0;
System.out.println(n1 / n2);
} catch (NullPointerException e) {
System.out.println("NullPointerException异常");
} catch (ArithmeticException e) {
System.out.println("ArithmeticException异常");
} catch (Exception e) {
System.out.println("Exception异常");
} finally {
System.out.println("finally-1");
}
System.out.println("程序继续------1");
try {
System.out.println(1 / 0);
} finally {
System.out.println("finally-2");
}
System.out.println("程序继续------2");
}
}
class Person {
public String name;
public Person(String name) {
this.name = name;
}
}
3. 执行顺序
- 如果没有出现异常,则执行try块的所有语句,不执行catch块中的语句,如果有finally,最后还需执行finally里面的语句
- 如果出现异常,则try块中异常发生后,try块剩下的一句不再执行。将执行catch块中的语句,如果有finally,最后还需要执行finally里面的语句
4. 代码示例
package Java.Exception;
/**
* @author 鹿青舟
* @version 1.0
*/
public class Try_catch_catch {
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);
System.out.println("两个数的商为:" + res);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println(e.getMessage());
} catch (NumberFormatException e) {
System.out.println(e.getMessage());
} catch (ArithmeticException e) {
System.out.println(e.getMessage());
}
}
static double cal(int n1, int n2) {
return n1 / n2;
}
}
七、throws异常处理
1. 基本介绍
- 如果一个方法(中的语句执行时)可能生成某种异常,但是并不能确定如何处理这些异常,则此方法应显示地声明抛出异常,表明该方法将不对这些异常进行处理,而由该方法的调用者负责处理
- 在方法声明中用throws语句可以声明抛出异常的列表,throws后年的异常类型可以是方法中产生的异常类型,也可以是它的父类
2. 注意示例
- 对于编译异常,程序中必须处理,比如用try- catch或者throws其中一个
- 对于运行时异常,程序中如果没有处理,默认就是throws的方式处理
- 子类重写父类的方法,对抛出异常的规定:子类重写的方法,所抛出的异常类型要么和父类抛出的异常一致,要么为父类抛出异常的子类型
- 在throws过程中,如果有方法try-catch,就相当于处理异常,就可以不必throws
3. 代码示例
package Java.Exception;
/**
* @author 鹿青舟
* @version 1.0
*/
public class ThrowExercise {
public static void main(String[] args) {
try {
ReturnExceptionDemo.fun();
} catch (Exception e) {
System.out.println(e.getMessage());
}
System.out.println("-------------");
try {
System.out.println("进入方法");
throw new RuntimeException("制造异常");
// int n = 1 / 0;
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
System.out.println("finally");
}
}
}
class ReturnExceptionDemo {
static void fun() {
try {
System.out.println("进入方法");
throw new RuntimeException("制造异常");
// int n = 1 / 0;
} finally {
System.out.println("finally");
}
}
}
八、自定义异常
1. 基本介绍
当程序中出现了某些“错误”,但该错误信息并没有在Throwable子类中描述处理,这个时间可以自己设计异常类,用于描述该错误信息
2. 步骤
1⃣️定义类:自定义异常类名(程序员自己写)继承 Exception或RuntimeException
2⃣️如果继承Exception,属于编译异常
3⃣️如果继承RuntimeException,属于运行类型(一般继承运行类型)
3. 代码示例
package Java.Exception;
/**
* @author 鹿青舟
* @version 1.0
*/
public class CustomException {
public static void main(String[] args) {
int age = 20;
if (!(age >= 18 && age <= 120)) {
throw new ageException("年龄应该在18-120之间");
}
System.out.println("你的年龄正确");
}
}
class ageException extends RuntimeException {
public ageException(String message) {
super(message);
}
}
九、throw和throws的对比
分类 | 意义 | 位置 | 后面跟的东西 |
---|---|---|---|
throws | 异常处理的一种方式 | 方法声明处 | 异常类型 |
throw | 手动生成异常对象的关键字 | 方法体中 | 异常对象 |