【Java笔记】20 异常
一、异常概念
程序执行中发生的不正常情况称为异常,语法错误和逻辑错误不是异常
异常分为两大类:
- Error(错误):虚拟机无法解决的严重问题,如:JVM系统内部错误、资源耗尽等
- Exception:其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理,如:空指针访问,试图读取不存在的文件
- 运行时异常 程序运行时发生的异常 可以不做处理
- 编译时异常 编程时由编译器检查出的异常 必须处理
public class Exception01 {
public static void main(String[] args) {
int num1 = 10; int num2 = 0;
// 抛出异常ArithmeticException
// try-catch异常处理机制来解决
// 代码块选中,快捷键ctrl+alt+t,选中try-catch
// 异常处理后,即使出现了异常,程序可以继续运行
try {
int res = num1 / num2;
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("程序继续运行....");
}
}
二、异常体系图
三、五个常见的运行时异常
- 空指针异常NullPointerException
当程序试图在需要对象的地方使用null时,抛出该异常
public class NullPointerException_ {
public static void main(String[] args) {
String name = null;
System.out.println(name.length());
}
}
Exception in thread “main” java.lang.NullPointerException
at java20.exception.NullPointerException.main(NullPointerException_.java:6)
- ArithmeticException数学运算异常 如除以0
- ArrayIndexOutOfBoundsException数组下标越界异常 索引为负或等于数组大小
- ClassCastException试图将对象强制转换为不是实例的子类时
public class Exception02 {
public static void main(String[] args) {
A a = new B(); // 向上转型可以
B b = (B)a; // 向下转型 a本身就指向B 可以
C c = (C)a;
}
}
class A{ }
class B extends A{}
class C extends A{}
Exception in thread “main” java.lang.ClassCastException: java20.exception.B cannot be cast to java20.exception.C
at java20.exception_.Exception02.main(Exception02.java:7)
- 数字格式不正确异常 将字符串转成一种数值类型,但该字符串不能转换为适当格式时,抛出
public class NumberFormatException_ {
public static void main(String[] args) {
String name = "aaa";
int num = Integer.parseInt(name);//NumberFormatException
}
}
四、编译异常
在编译期间,就必须处理的异常
常见的编译异常
- SQLException 操作数据库时,查询表可能发生异常
- IOException 操作文件时
- FileNotFoundException 操作不存在的文件时
- ClassNotFoundException 加载类而类不存在时
- EOFException 操作文件到达文件末尾
- IllegalAraguementException 参数异常
五、异常处理
- try-catch-finally 捕获异常,自行处理
try{
代码可能有异常处
发生了异常,异常发生后面的代码不会执行,直接进入到catch块
}catch(Exception e){
捕获到异常系统将异常封装成Exception对象e,传递给catch
得到异常对象后,自行处理
可以有多个catch语句,捕获不同的异常,进行不同的业务处理,父类异常在后,子类异常在前
}finally{
不管try代码块是否有异常发生,始终要执行finally
通常将释放资源的代码放在finally、
可以没有finally
}
根据需要在程序中有多个try-catch块
try-finally配合使用,没有捕获异常,程序崩溃。应用场景:执行一段代码,不管是否发生异常,都执行某个业务逻辑
例:如果用户输入的不是一个整数,就提示他反复输入,直到输入一个整数为止public class TryCatchDetail02 {
public static void main(String[] args) {
//如果try 代码块有可能有多个异常,使用多个catch 分别捕获不同的异常,相应处理
//子类异常在前面,父类异常在后面
try {
Person person = new Person();
person = null;
System.out.println(person.getName());//NullPointerException
int n1 = 10;
int n2 = 0;
int res = n1 / n2;//ArithmeticException
} catch (NullPointerException e) {
e.printStackTrace();
} catch (ArithmeticException e) {
System.out.println(e.getMessage());
}
finally {
}
}
}
class Person{
private String name = "aaa";
public String getName(){
return name;
}
}
public class TryCatchDetail03 {
public static void main(String[] args) {
try {
int n1 = 10;
int n2 = 0;
System.out.println(n1 / n2);
} finally {
System.out.println("执行了finally");
}
System.out.println("程序继续执行..");
}
}
Exception in thread “main” java.lang.ArithmeticException: / by zero
at java20.exception_.TryCatchDetail03.main(TryCatchDetail03.java:8)
执行了finallySystem.out.println(“程序继续执行..”); 这句话不执行
public class TryCatchExercise04 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int num = 0;
String inputStr = "";
while (true){
System.out.println("请输入一个整数:");
inputStr = scanner.next();
try {
num = Integer.parseInt(inputStr);
break;
} catch (NumberFormatException e) {
System.out.println("输入的不是一个整数");
}
}
System.out.println("输入的值是" + num);
}
}
- throws 抛出异常,交给调用者(方法)处理,最顶级的处理者是JVM
try-catch和throws二选一,没有显式的选择try-catch和throws ,默认throws
throws语句可以声明抛出异常的列表,throws后面的异常类型可以是方法中产生的异常类型,也可以是它的父类
- 注意事项
编译异常,程序中必须处理
运行时异常,程序中没有处理,默认就是throws
子类重写父类的方法时,子类重写的方法,所抛出的异常类型要么和父类的抛出异常一致,要么为父类抛出异常类型的子类型
throws过程中,如果方法有try-catch,就相当于处理异常,不必再throws
六、自定义异常
- 基本概念
程序中出现某些错误,但错误信息没有再Throwable子类中处理,自己设计异常类 - 步骤
- 定义类:自定义异常类名 继承Exception或RuntimeException
- 如果继承Exception,属于编译异常
- 如果继承RuntimeException,属于运行异常,一般都继承RuntimeException
例:年龄要求18-120之间,否则抛出自定义异常
public class CustomException {
public static void main(String[] args){
int age = 180;
if(!(age >= 18 && age <= 120)){
throw new AgeException("年龄不在范围");
}
System.out.println("范围正确");
}
}
// 一般情况下,我们自定义异常是继承RuntimeException
// 即把自定义异常做成运行时异常,好处是,可以使用默认的处理机制
class AgeException extends RuntimeException {
public AgeException(String message) {
super(message);
}
}
七、throw和throws
意义 | 位置 | 后面跟的东西 | |
---|---|---|---|
throws | 异常处理的一种方式 | 方法声明处 | 异常类型 |
throw | 手动生成异常对象的关键字 | 方法体中 | 异常对象 |