异常
Exception是什么
- 概念:程序中出现的各种异常的总称
- 具体:Java中所有异常类的父类
Exception与Error的区别
- Exception:不正常的事情,但是可以解决
- Error:不可以解决,或者解决起来非常麻烦
Exception的分类
未检查异常(又叫运行时异常)
-
父类:RuntimeException(RuntimeException的父类也是Exception)
-
解释:编辑器未报错,程序运行时被抛出的异常。
-
产生:由程序员马虎引起的异常,属于程序员意料之外的异常。例如空指针异常,数组越界异常。
-
解决:该异常不要求程序员做相关预防措施,只需要更正代码即可
-
示例:
- NullPointerException
- ArrayIndexOutOfBoundException
- StringIndexOutOfBoundException
- ClassCastException
- EOFException
- CurrentModifyException
程序遇到运行时异常时会立即结束,不会继续运行之后的代码
已检查异常
-
父类:Exception
-
解释:编辑器报错,编译不通过。
-
产生:不是程序本身导致,有可能由外部因素引起。例如使用IO时发现指定文件不存在,则抛出FileNotFoundException
-
解决:该异常程序员无法解决,但是可以预测并作出相应预防措施,当异常发生时启动预防措施
检查的执行者是编辑器,编辑器没检查出来的异常叫未检查异常,编辑器检查出来的异常叫已检查异常
处理已检查异常的方式
try-catch(-finally)
在出现异常的方法中,捕获并处理相关异常,可以处理未检查异常。
try-catch相当于if-else
- try:正常情况下,执行try中的代码。try必须存在,且只能有一个。
- catch:出现异常时,由catch抓取异常并执行相应catch中的代码。catch必须存在,且可以有多个。
- finally:除了System.exit(0)之外的任何情况,finally中的代码都会执行,所以通常用来执行关闭流、JDBC链接等释放资源的操作。finally相当于try-catch的附加模块,可以省略;如果写了,那只能存在一个。
注意:catch按照从上往下的顺序进行抓取异常,有父子关系的异常应严格按照权限范围的从小到大排列(子类在上,父类在下),因为catch不会多次捕获同一个异常,即一旦某个异常被catch捕获过一次之后,下面的catch将不会继续捕获该异常;没有父子关系的异常则可以随意排序。
package day20191128;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class Demo01 {
public void T() {
method();
}
public void method() {
/**
*try、catch、finally是三个独立的代码块,其中声明的变量都是局部变量,无法互通
*/
try {
FileInputStream f = new FileInputStream("a.txt");
} catch (FileNotFoundException e) {
/**
* FileNotFoundException e:创建异常的实例对象
* printStackTrace():打印错误信息
* catch中的内容可自定义
*/
System.out.println("发生错误!");
e.printStackTrace();
}catch(IOException e){
/**
*IOEception是FileNotFoundException的父类,所以需要放在下面
*/
e.printStackTrace();
}catch(..){
}finally{
}
/**
* try-catch之后的代码会正常运行
*/
System.out.println(1);
}
}
注意:异常点之后的代码不会被执行;try-catch之后的代码会正常运行
throws
在除主方法外的方法声明上抛出方法,方法调用者处理被抛出异常(也可以选择继续向外抛出,但是最后一级调用者必须处理异常)。注意:throws可以同时抛出多个异常,用逗号分隔。
package day20191128;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class Demo02 {
public static void main(String[] args) {
Test t = new Test();
try {
t.method();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
class Test{
public void method() throws FileNotFoundException {
FileInputStream f = new FileInputStream("a.txt");
}
}
注意:throws之后的语句不会执行
throw
throw也是抛出异常的一种方式,与throws有以下区别
-
throws通常是编辑器强制要求抛出(异常必须存在),throw是程序员人为地制造一个异常并抛出
-
throws在方法声明中抛出异常,抛给方法调用者;throw在方法体内执行,抛给方法本身
-
throws抛出的是异常的名称,throw抛出的是异常的实例对象
-
throws可以同时抛出多个异常,throw只能抛出一个
-
throws抛出的异常可能会发生也可能不会发生,throw的语句被执行说明异常必定发生
方法调用者也要处理被throw抛出的异常
- 抛出
package day20191128;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class Demo02 {
public static void main(String[] args) {
Test t = new Test();
try {
t.method();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class Test{
public void method() throws FileNotFoundException {
throw new java.io.FileNotFoundException("文件未找到");
}
}
- 方法内处理
package day20191128;
public class Demo02 {
public static void main(String[] args) {
Test t = new Test();
t.method();
}
}
class Test{
public void method() {
try {
throw new java.io.FileNotFoundException("文件未找到");
}catch(Exception e) {
e.printStackTrace();
}
}
}
注意:throw之后的语句同样无法执行
关于finally的小扩展
代码如下,问最终输出结果是什么?
package day20191128;
public class Demo03 {
public static void main(String[] args) {
Test t = new Test();
System.out.println(t.method());
System.out.println(t.a);
}
}
class Test{
int a = 18;
public int method() {
try {
int i = a/0;
return a;
}catch(Exception e) {
return a;
}finally {
a++;
}
}
}
答:以上代码的最终输出结果为18,19。
分析:从答案中我们可以看出finally在catch的return之后执行,众所周知,return的作用是返回结果并结束方法,然而结果却与我们的认知相悖,这是为什么呢?这是由return的执行过程决定的,return的执行分为两部分:
- 第一次执行到return:将结果保存到缓冲区,不直接返回
- 监测到所有代码执行完毕:将缓冲区中的结果返回,结束方法
finally的执行是在return的第一步之后、第二步之前,因为return是返回缓冲区中的结果,所以a++影响不到方法返回值,最终得到了18,19的结果。
自定义异常
package day20191128;
/**
*
* @author DL
* 用户名或密码错误异常
* 已检查异常:extends Exception
* 未检查异常:extends RuntimeException
*/
public class IdOrPwdException extends Exception{
public IdOrPwdException() {
super("用户名/密码错误");
// TODO Auto-generated constructor stub
}
public IdOrPwdException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
}
public IdOrPwdException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
public IdOrPwdException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
public IdOrPwdException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
}