JAVA-异常处理
1.异常概述
1. 异常是运⾏时错误(程序执⾏期间发⽣的事件).
2. 异常是从⽅法抛出的,⽅法的调⽤者可以捕获以及处理该异常.
3. 异常处理使得程序可以处理运⾏时的错误并且继续通常的执⾏.
4. 运⾏时错误: 程序运⾏过程中,若JVM检测出⼀个不可能执⾏的操作.
eg.越界下标访问: ArrayIndexOutOfBoundsException
5. 异常: JAVA中运⾏时错误会作为异常抛出. 异常为⼀种对象.
⼤致模板:
try{
Code to run;
A statement or a method that may  throw an exception;
More code to run;
}
catch(type ex){
Code to process the exception;
}
1. 很多库⽅法都会抛出异常,此时throw可省
2. ⼀个异常可能是通过try块中的throw语句直接抛出,或者调⽤⼀个可能会抛出异常的⽅法⽽抛出
3. 若try块中内容正常执⾏,不会引起异常
4. 若try块中内容(⽅法)遇到⼀个异常,其会抛出⼀个异常给它的调⽤者,这个调⽤者的catch处理该异常
拋出(throw)异常:⽣成异常对象,并把它提交给运⾏时系统。
捕获(catch)异常:运⾏时系统在⽅法的调⽤栈中查,直到到能够处理该类型异常的对象。
2.异常类型
Java通过⾯向对象来处理异常,即异常是对象,⽽对象都⽤类来定义。异常的根类为java.lang.Throwable
异常类的类型:
1. 系统错误Error: Java虚拟机抛出,描述内部系统错误.
发⽣时:通知⽤户以及尽量稳妥地终⽌程序.
2. 异常Exception:描述由程序和外部环境引起的错误.发⽣时:能被程序捕获和处理
1. 运⾏时异常(unchecked): RuntimeException类表⽰,程序设计错误。如 NullPointerException、IndexOutOfBoundsException 等,
这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常⼀般由程序逻辑错误引起,程序应该从逻辑⾓度尽可能避免这类异常的发⽣。
2. ⾮运⾏时异常(checked):RuntimeException以外的异常。从程序语法⾓度讲是必须进⾏处理的异常,如果不处理,程序就不能
编译通过。如 IOException、ClassNotFoundException 等以及⽤户⾃定义的 Exception 异常(⼀般情况下不⾃定义检查异
常)。
3. RuntimeException, Error以及其⼦类都称为免检异常,其他异常称为必检异常(编译器会强制程序员检查并通过try-catch来处理/⽅法头中
声明)
2.1 Java常见运⾏时异常:
2.2 Java常见⾮运⾏时异常
2.3 Error与Exception⽐较
1. Exception 是程序正常运⾏过程中可以预料到的意外情况,并且应该被开发者捕获,进⾏相应的处理。
Exception ⼜分为可检查(checked)异常和不检查(unchecked)异常,可检查异常在源码⾥必须显⽰的进⾏捕获处理,这⾥是编译期检查的⼀部分。不检查异常就是所谓的运⾏时异常,通常是可以编码避免的逻辑错误,具体根据需要来判断是否需要捕获,并不会在编译器强制要求。
2. Error 是指正常情况下不⼤可能出现的情况,绝⼤部分的 Error 都会导致程序处于⾮正常、不可恢复状态。所以不需要被开发者捕获。
3.异常处理
异常的处理器都是通过从当前⽅法开始,沿着⽅法调⽤链,按照异常的反向传播⽅向到的.
Java异常处理模型基于三种操作: 声明异常,抛出异常,捕获异常;五个关键字:try,catch,throw,throws,finally
1. try catch语句⽤于捕获并处理异常
2. finally语句在任何情况下(除特殊情况)都是必须执⾏的代码
3. throw语句⽤于抛出异常
4. throws语句⽤于声明可能会出现的异常
3.1 声明异常
当⼀个⽅法产⽣⼀个它不处理的异常时,那么就需要在该⽅法的头部声明这个异常,以便将该异常传递到⽅法的外部进⾏处理。使⽤throws 声明的⽅法表⽰此⽅法不处理异常。
具体格式: returnType method_name(paramList) throws Exception 1,Exception2,…{…}
3.1.1 使⽤思路
使⽤ throws 声明异常的思路是,当前⽅法不知道如何处理这种类型的异常,该异常应该由向上⼀级的调⽤者处理;如果 main ⽅法也不知道如何处理这种类型的异常,也可以使⽤ throws 声明抛出异常,该异常将交给 JVM 处理。
JVM 对异常的处理⽅法是,打印异常的跟踪栈信息,并中⽌程序运⾏,这就是前⾯程序在遇到异常后⾃动结束的原因。
3.1.2 注意事项
1. Java中当前语句必属于某个⽅法.每个⽅法都必须声明其可能抛出的必检异常类型.
2. Java不要求在⽅法中显式声明Error和RuntimeException,其他异常都必须显式声明.
3. 关键字throw表明method⽅法可能会抛出IOException异常;若可能抛出多个异常可⽤,分隔.
4. 若在⽗类中的⽅法没有声明异常,则不能在⼦类中对其重写时声明异常.
3.1.3 使⽤限制
⼦类⽅法声明抛出的异常类型应该是⽗类⽅法声明抛出的异常类型的⼦类或相同,⼦类⽅法声明抛出的异常不允许⽐⽗类⽅法声明抛出的异常多。
3.1.4 使⽤⽰例
点击查看代码
以上代码,⾸先在定义 readFile() ⽅法时⽤ throws 关键字声明在该⽅法中可能产⽣的异常,然后在 main() ⽅法中调⽤ readFile() ⽅法,并使⽤ catch 语句捕获产⽣的异常。
3.2 抛出异常
3.1.1 使⽤思路
注:声明异常关键字:throws, 抛出异常关键字:throw
throw 语句⽤来直接拋出⼀个异常,后接⼀个可拋出的异常类对象throw ExceptionObject;
当 throw 语句执⾏时,它后⾯的语句将不执⾏,此时程序转向调⽤者程序,寻与之相匹配的 catch 语句,执⾏相应的异常处理程序。如果没有到相匹配的 catch 语句,则再转向上⼀层的调⽤程序。这样逐层向上,直到最外层的异常处理程序终⽌程序并打印出调⽤栈情况。
3.3.2 注意事项
1. 检测到错误的程序可以创建⼀个合适的异常类型的实例并抛出它
2. ExceptionObject必须是Throwable类或其⼦类的对象。
3. 如例所⽰,IllegalArgumentException是Java API中的⼀个异常类.
通常,JAVA API中的每个异常类都⾄少有两个构造⽅法:⼀个⽆参和⼀个带String参.String参称为异常消
息,可通过⼀个异常对象调⽤getMessage()获取
4. ⼀般通过if-else来使⽤
eg.要求⽅法的参数⾮负,但传⼊了⼀个负参数值:
IllegalArgumentException ex =
new IllegalArgumentException("Wrong Argument");
int i = in.nextInt();
if(i > 0) ...;
else throw ex; //1
//throw new IllegalArgumentException("Wrong Argument"); //2
3.1 & 3.2 throw与throws⽐较区别
1. throws ⽤来声明⼀个⽅法可能抛出的所有异常信息,表⽰出现异常的⼀种可能性,但并不⼀定会发⽣这些异常;
throw 则是指拋出的⼀个具体的异常类型,执⾏ throw 则⼀定抛出了某种异常对象。
2. 通常在⼀个⽅法(类)的声明处通过 throws 声明⽅法(类)可能拋出的异常信息,
⽽在⽅法(类)内部通过 throw 声明⼀个具体的异常信息。
3. throws 通常不⽤显⽰地捕获异常,可由系统⾃动将所有捕获的异常信息抛给上级⽅法;
throw 则需要⽤户⾃⼰捕获相关的异常,⽽后再对其进⾏相关包装,最后将包装后的异常信息抛出。
3.3 捕获异常
3.3.1 程序⽰例
try {
逻辑程序块
} catch(ExceptionType1 e) {
处理代码块1
} catch (ExceptionType2 e) {
处理代码块2
throw(e);    // 再抛出这个"异常"
} finally {
释放资源代码块
}
3.3.2 过程详解
1. 在try-catch中捕获及处理异常
2. 处理异常的代码称为异常处理器
查异常处理器:
若try块某条语句抛出异常,Java会跳过try中剩余语句,然后查异常处理器.
从当前⽅法开始,沿着⽅法调⽤链,按照异常的反向传播⽅向到这个处理器.
从第⼀个到最后⼀个逐个检查catch块,判断在catch块中的异常实例是否是该异常对象的类型.
若没发现则推出这个⽅法并将异常传递给这个⽅法的调⽤者,继续同样的过程来处理器.
若没到处理器,程序会终⽌并在控制台上打印错误信息.
到并处理之后,程序会跳过 try 语句块中剩余的语句,转到 catch 语句块后⾯的第⼀条语句开始执⾏。
3. 如果 try 语句块中没有异常发⽣,那么 try 块正常结束,后⾯的 catch 语句块被跳过,程序将从 catch 语句块后的第⼀条语句开始执
⾏。
4. ⼀般情况下,⽆论是否有异常抛出,都会执⾏finally语句块中的语句。
5. finally⼀般⽤于关闭try中打开的物理资源(JVM不会回收物理资源,只会回收堆内存中对象所占⽤的内存)
6. 查处理器的过程称为捕获异常
3.3.3 catch可选输出信息
处理代码块1或处理代码块2可使⽤如下⼏个⽅法输出相应异常信息:
java.lang.Throwable作⽤
getMessage():String返回描述该异常对象的信息(含参构造函数的str) ,输出错误的性质。
toString():String返回三个字符串的连接: 1)异常类的全名 2) (⼀个冒号和⼀个空⽩) 3) getMessage()⽅法printStackTrace():void控制台上打印Throwable对象和它的调⽤栈的跟踪信息,指出异常的类型、性质、栈层次及出现在程序
中的位置
getStackTrace():
返回⼀个栈跟踪元素的数组,表⽰和该异常对象相关的栈的跟踪信息
StackTraceElement[]
toString()给出异常的类型与性质。
3.3.4 使⽤机制&注意事项
使⽤机制:
1. 在⽅法中⽤ try catch 语句捕获并处理异常,catch 语句可以有多个,⽤来匹配多个异常。
2. 对于处理不了的异常或者要转型的异常,在⽅法的声明处通过 throws 语句拋出异常,即由上层的调⽤⽅法来处理。
注意事项:
1. 各种异常类可以从⼀个共同的⽗类中派⽣.若⼀个catch块可捕获⼀个⽗类的异常对象,则其可以捕获那个⽗类所有⼦类的异常对象
2. catch块中异常被指定的顺序: 必须为先⼦类后⽗类(先具体后笼统),否则⼦类捕获不到。(能更具体的处理最好进⾏更具体的处理)
3. try 后⾯的花括号{ }不可以省略,try 块⾥声明的变量只是代码块内的局部变量,它只在 try 块内有效
4. catch 块后的花括号{ }也不可以省略。
5. try-catch-finally中try是必须的,catch和finally都是可选的(但⾄少出现其⼀)
6. 除⾮在 try 块、catch 块中调⽤了退出虚拟机的⽅法it(int status),否则不管在 try 块或者 catch 块中执⾏怎样的代码,出现怎
样的情况,异常处理的 finally 块总会执⾏。
7. 通常情况下不在 finally 代码块中使⽤ return 或 throw 等导致⽅法终⽌的语句,否则将会导致 try 和 catch 代码块中的 return 和 throw 语
句失效
3.4 ⾃动资源管理
3.4.1 ⽰例⽤法
try (声明或初始化资源语句) {
// 可能会⽣成异常语句
} catch(Throwable e1){
// 处理异常e1
} catch(Throwable e2){
// 处理异常e1
} catch(Throwable eN){
// 处理异常eN
}
此时当 try 代码块结束时,⾃动释放资源。不再需要显式的调⽤ close() ⽅法,该形式也称为“带资源的 try 语句”。
3.4.2 注意事项
1. try 语句中声明的资源被隐式声明为 final,资源的作⽤局限于带资源的 try 语句。
2. 可以在⼀条 try 语句中声明或初始化多个资源,每个资源以;隔开即可。
3. 需要关闭的资源必须实现了 AutoCloseable 或 Closeable 接⼝。
4.何时使⽤异常
1. 当错误需要被⽅法的调⽤者来处理时,⽅法应该抛出⼀个异常
2. 异常处理通常需要更多的时间和资源(初始化异常对象,从调⽤栈返回,沿着⽅法调⽤链来传播异常以到其异常处理器)
3. 异常发⽣在⽅法中,若想让该⽅法的调⽤者处理异常,应创建⼀个异常对象并将其抛出.(若能在发⽣异常的⽅法中处理异常则不需抛出或
使⽤异常)
4. 个别⽅法中的简单错误最好进⾏局部处理(if)
5. 当必须处理不可预料的错误状况时应使⽤try-catch块(不要⽤其处理简单的,可预料的情况)
5.重新抛出异常
若异常处理器不能处理⼀个异常或只是简单地希望其调⽤者注意到该异常,Java匀速该异常处理器重新抛出异常.
eg.
try{
statement;
}catch(Exception ex){
operation before exits;
throw ex;
}
语句throw ex重新抛出异常给调⽤者,以便调⽤者的其他处理器获得处理ex的机会.(已经捕获了还希望得到进⼀步处理)
6.创建⾃定义异常类
⾃定义异常类需要继承 Exception 类或其⼦类;⾃定义运⾏时异常类需继承 RuntimeException 类或其⼦类。
语法格式:
<class><⾃定义异常名(XXXException)><extends><Exception>
⾃定义异常类⼀般包含两个构造⽅法:⼀个是⽆参的默认构造⽅法,另⼀个构造⽅法以字符串的形式接收⼀个定制的异常消息,并将该消息传递给超类的构造⽅法。
点击查看⾃定义异常类实例nextint()方法
点击查看运⾏结果

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。