JavaSe:异常处理
异常处理
🎈概述:
-
Error(错误): Java虚拟机无法解决的严重问 题。如:JVM系统内部错误、资源耗尽等严重情况。比如:StackOverflowError(栈溢出)和OOM(OutOfMemory:堆溢出)。一般不编写针对性的代码进行处理。
一般不针对性的写解决Error的代码
-
Exception(异常): 其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。
- 空指针访问
- 试图读取不存在的文件
- 网络连接中断
- 数组角标越界
-
对于这些错误,一般有两种解决方法
- 一是遇到错误就终止程序的运行。
- 程序员在编写程序时,就考虑到错误的检测、错误消息的提示,以及错误的处理。
-
捕获错误最理想的是在编译期间,但有的错误只有在运行时才会发生。
比如:除数为0,数组下标越界等
🎈分类:
-
编译时(checked)异常(非RuntimeException)
- 是指编译器要求必须处置的异常。即程序在运行时由于外界因素造成的一般性异常。编译器要求Java程序必须捕获或声明所有编译时异常。
- 对于这类异常,如果程序不处理,可能会带来意想不到的结果。
-
运行时(unchecked)异常(RuntimeException)
-
是指编译器不要求强制处置的异常。一般是指编程时的逻辑错误,是程序员应该积极避免其出现的异常。java.lang.RuntimeException类及它的子类都是运行时异常。
-
对于这类异常,可以不作处理,因为这类异常很普遍,若全处理可能会对
程序的可读性和运行效率产生影响。
-
🎈常见异常举例
-
RuntimeException(可以编译)
-
NullPointerException
1
2String a = null;
System.out.println(a.charAt(0)); -
ArrayOutOfBoundsException
1
2int[] arr = new int[5];
System.out.println(arr[6]); -
ClassCastException(类强制转换异常)
1
2Object obj = new Object();
String str = (String) obj; -
NumberFormatException
1
2
3
4
5String str="123";
str="abc";
int num=Integer.parseInt(str);
//Integer.parseInt(String);
//String 必须为纯数字 -
InputMismatchException
1
2Scanner in = new Scanner(System.in);
int score = in.nextInt(); // key in dfsd -
ArithmeticException(算术异常)
1
2int a = 14, b = 0;
System.out.println(a / b);
-
-
CompileTimeException(编译时异常)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19package src.SUMMER_java;
public class Day0529 {
public static void main(String[] args) {
}
public void test() throws IOException {
File file = new File("hello.txt");
FileInputStream fis = new FileInputStream("hello.txt");
int data = fis.read();
while (data != -1) {
System.out.print((char) data);
}
fis.close();
}
}
//报错:IOException cannot be resolved to a type
//FileInputStream cannot be resolved to a type
🎈异常处理方式
在编写程序时,经常要在可能出现错误的地方加上检测的代码,如进行x/y运算时,要检测分母为0,数据为空,输入的不是数据而是字符等。过多的if-else分支会导致程序的代码加长、臃肿,可读性差。因此采用异常处理机制。

⭐try-catch-finally
-
Java提供的是异常处理的抓抛模型。
-
一旦抛出异常后,其后的代码不在执行
-
Java程序的执行过程中如出现异常,会生成一个异常类对象,
该异常对象将被提交给Java运行时系统,这个过程称为抛出
(throw)异常。
-
异常对象的生成
- 由虚拟机自动生成:程序运行过程中,虚拟机检测到程序发生了问题,如果在当前代码中没有找到相应的处理程序,就会在后台自动创建一个对应异常类的实例对象并抛出——自动抛出。
- 由开发人员手动创建:Exception exception = new ClassCastException();——创建好的异常对象不抛出对程序没有任何影响,和创建一个普通对象一样。
-
如果一个方法内抛出异常,该异常对象会被抛给调用者方法中处
理。如果异常没有在调用者方法中处理,它继续被抛给这个调用
方法的上层方法。这个过程将一直继续下去,直到异常被处理。
这一过程称为捕获(catch)异常。
-
如果一个异常回到main()方法,并且main()也不处理,则程序运
行终止。
👉使用说明
-
使用try将可能出现异常的代码包装起来,在执行过程中,一旦出现异常,就会生成一个对应异常类的对象,根据对象的类型,去catch中进行匹配。
-
catch 中可以很多个,一旦try中的异常对象被catch匹配,就会进入catch中进行异常的处理,一旦处理完成(执行完catch中的代码),就会跳出try-catch结构(没有finally的话),继续执行下面的代码。
-
catch中的异常类型如果没有子父类关系,那么声明位置无所谓。
如果满足子父类关系,则要求子类要声明在父类的前面,否则会报错
//Thrown by a
Scannerto indicate that the token retrieved does not match the pattern for the expected type, or that the token is out of range for the expected type. -
常用的异常对象的处理方式:
- String getMessage() //String getMessage();
- printStacTrace() //跟报错一样显示错误信息
-
在try中声明的变量,出了try之后不能再调用。(想要使用,定义在try外面即可)
1 | package src.SUMMER_java; |
👉finally 的使用
- finally 是可选的
- finally中的代码必定会执行。即便catch中出现了新的异常或者是catch中==有return语句==,
1 | package src.SUMMER_java; |
🎈try-catch-finally捕获异常总结:
- 主要处理编译时异常(例如打开文件,非语法错误),使得程序在编译时不报错,但是运行时仍然可能报错。相当于使用try-catch-finally将一个编译时可能出现的异常,延迟到运行时出现。
- 开发中由于运行时异常较为常见,因此通常不针对运行时异常编写try-catch-finally,针对编译时的异常,一定要考虑异常的处理。
⭐throws + 异常类型
- 🎈"throws "+异常类型 要写在方法的执行处,指明此方法执行时,可能会抛出的异常类型,一旦当方法执行时,出现异常,仍然会在代码执行处生成一个异常类,如果此对象满足throws抛出的异常类型,就会向上一级抛出,异常后面的代码就不再执行。
- 🎈体会:
- try-catch-finally真正的处理了异常
- throws只是将异常抛给了方法的调用者,并没有真正处理异常
👉重写方法声明抛出异常的原则
-
子类重写的方法不能抛出比被重写方法范围更大的异常类型。
FileNotFoundException < IOException,换句话说,子类抛出的异常应当能被父类方法抛出的异常兼容。
如果父类方法没有throws方式抛出异常,子类方法也不能使用throws
Exception IOException is not compatible with throws clause in Dad.method_1()
1
2
3
4
5
6
7
8
9
10
11
12
13//Right code
class Dad {
// public void method_1() throwsFileNotFoundException { //wrong answer
public void method_1() throws FileNotFoundException, IOException {
}
}
class Son extends Dad {
public void method_1() throws IOException {
}
} -
执行的方法中,先后又调用了另外几个方法,这几个方法是递进关系执行的,我们建议这几个方法使用throws的方式进行处理,而执行的方法A,可以考虑yrt-catch-finally方式进行处理。
-
不建议两者同时使用。
⭐手动抛出异常
-
前面两种讲的都是系统自动生成的异常类,Java异常类对象除在程序执行过程中出现异常时由系统自动生成并抛出,也可根据需要使用人工创建并抛出。
-
步骤:
-
首先要生成异常类对象,然后通过throw语句实现抛出操作(提交给Java运行环境)。
1
2
3
4
5
6
7
8
9
10
11
12public static void main(String[] args) throws Exception {
test02();
}
public static void test02() throws Exception {
int id;
Scanner in = new Scanner(System.in);
id = in.nextInt();
if (id < 0) {
throw new Exception("您输入的数据非法!");
}
} -
可以抛出的异常必须是Throwable或其子类的实例。下面的语句在编译时将会产生语法错误:
1
throw new String("want to throw");
-
⭐用户自定义异常类
-
一般地,用户自定义异常类都是RuntimeException的子类。
-
自定义异常类通常需要编写几个重载的构造器。
-
自定义异常需要提供serialVersionUID
-
自定义的异常通过throw抛出。
-
自定义异常最重要的是异常类的名字,当异常出现时,可以根据
名字判断异常类型。
1 |
|











