异常: 在Java语言中,将程序中发生的不正常情况称为“异常”(开发过程中的语法错误和逻辑错误不是异常)
异常(广义)分类:
1. Error: Java虚拟机无法解决的严重问题,如:JVM系统内部错误、资源耗尽等严重情况(栈溢出-StackOverFlowError;内存溢出-Out of Memory,OOM),一般不编写针对性的代码进行处理
2. Exception(狭义异常):其他因编程错误或偶然的外在因素导致的一般性问题,如空指针访问、试图读取不存在的文件、网络连接中断、数组角标越界,可以使用针对性的代码进行处理
错误解决方式:
1. 遇到错误就终止程序的运行
2. 程序员在编写程序时,就考虑到错误的监测、错误消息的提示,以及错误的处理
错误捕获:
*捕获错误最理想的是在编译 期间,但有的错误只有在运行时才会发生,如除数为0,数组下标越界等
从而,存在 编译时异常 / 受检checked异常——Javac.exe 和 运行时异常 / 非受检unchecked 异常——java.exe
问题: 编写程序时,经常要在可能出现错误的地方加上检测的代码,一般会使用 i f if if判断,但过多的 i f − e l s e if-else if−else判断会导致程序的代码加长、臃肿,可读性差
解决: 采用异常处理机制
Java异常处理:java的异常处理机制是将异常处理的程序代码集中在一起,与正常的程序代码分开,使得程序简洁、优雅,并易于维护
异常的处理: 抓抛模型
1. 过程一:"抛”:程序在正常执行的过程中,一旦出现异常,就会在异常代码处生成一个对应异常类的对象——一旦抛出对象以后,其后的代码就不再执行
异常对象的产生:①系统自动生成的异常对象②手动生成一个异常对象并抛出( t h r o w throw throw)
2. 过程二:“抓”:异常的处理方式:① t r y − c a t c h − f i n a l l y try-catch-finally try−catch−finally;② t h r o w s throws throws
注 t h r o w throw throw 和 t h r o w s throws throws 的区别:
t h r o w throw throw 表示抛出一个异常类的对象,生成一个异常对象;声明在方法体内
t h r o w s throws throws 属于异常处理的一种方式;声明在方法的声明处
try{
//可能出现异常的代码
}catch(异常类型1 变量名1){
//处理异常的方式1
}catch(异常类型2 变量名2){
//处理异常的方式2
}
...
finally{
//一定会执行的代码
}
说明:
1. f i n a l l y finally finally 可选
2. 使用 t r y try try将可能出现异常的代码包装起来,在执行过程中,一旦出现异常,就会生成一个对应异常类的对象,然后根据此对象的类型去 c a t c h catch catch中进行匹配
3. 一旦 t r y try try中的异常对象匹配到某一个 c a t c h catch catch时,就进入 c a t c h catch catch中进行异常处理,一旦处理完成,就跳出当前的 t r y − c a t c h try-catch try−catch(没有 f i n a l l y finally finally) 的结构,继续执行后面的代码
4. c a t c h catch catch中的异常类型如果没有子父类关系,则谁声明在上,谁声明在下无所谓;若满足子父类关系,则要求子类一定声明在父类的上面,否则报错
5. 常用的异常对象处理方式:① S t r i n g g e t M e s s a g e ( ) String \quad getMessage() StringgetMessage() ; ② p r i n t S t a c k T r a c e ( ) printStackTrace() printStackTrace()
6. 在try结构中声明的变量,出了try结构以后,就不能再被调用了
7. t r y − c a t c h − f i n a l l y try-catch-finally try−catch−finally结构可以嵌套
try-catch-finally中的finally使用:
1. f i n a l l y finally finally 可选
2. f i n a l l y finally finally 中声明的代码一定会被执行, 即使catch中又出现异常了,或者try中有return语句,或者catch中有return语句等情况
3. 像数据库连接、输入输出流、网络编程Socket等资源,JVM无法自动回收,需要手动进行资源释放,此时的资源释放,就可以声明在finally中
注: finally中的fis.close:
1. 要考虑将fis的定义放在try-catch-fianlly外面;
2. 要考虑JVM不会自动释放fis资源,需要手动释放,所以放在finally中;
3. 要考虑当file没有创建成功时,fis就可能为空,进行资源释放时需要先判断是否为空,否则可能出现空指针异常;
4. 要考虑fisde 类型为输入流,可能出现IOException
s u m m a r y \bold{summary} summary
1. 使用 t r y − c a t c h − f i n a l l y try-catch-finally try−catch−finally处理编译时异常,使得程序在编译时不再报错,但运行时仍可能报错,相当于使用try-catch-fianlly将一个编译时可能出现的异常,延迟到运行时出现
2. 开发中,由于运行时异常较为常见,所以通常不针对运行时异常编写try-catch-finally,针对于编译时异常,一定要考虑异常处理
用法: 写在方法的声明处,指明此方法执行时,可能会抛出的异常类型;一旦当方法体执行时出现异常,仍会在异常代码出生成一个异常类的对象, 此对象满足 t h r o w s throws throws后异常类型时,就会被抛出;异常代码后续的代码就不再执行
注:
1. t r y − c a t c h − f i n a l l y try-catch-finally try−catch−finally:将真正的异常给处理掉了
2. t h r o w s throws throws的方式只是将异常抛给了方法的调用者,并没有真正将异常处理掉——>最后的调用者还是得用 t r y − c a t c h − f i n a l l y try-catch-finally try−catch−finally进行异常处理
异常对象的产生:①系统自动生成的异常对象②手动生成一个异常对象并抛出( t h r o w throw throw)
public class StudentTest {
public static void main(String[] args) {
try {
Student s = new Student();
s.regist(-2);
System.out.println(s);
} catch (Exception e) {
// throw new RuntimeException(e);
System.out.println(e.getMessage());
}
}
}
class Student{
int id;
public void regist(int id) throws Exception {
if(id> 0){
this.id = id;
}else{
// System.out.println("您输入的数据非法");
//手动抛出异常对象
// throw new RuntimeException("您输入的数据非法");
throw new Exception("您输入的数据非法");//包括编译+运行时异常,需要处理
}
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
'}';
}
}
如何自定义异常类?【点进某个异常类模仿者写】
1. 继承于现有的异常结构: R u n t i m e E x c e p t i o n RuntimeException RuntimeException、 E x c e p t i o n Exception Exception
2. 提供全局常量 s e r i a l V e r s i o n U I D serialVersionUID serialVersionUID
3. 提供重载的构造器
public class RuntimeException extends Exception {
static final long serialVersionUID = -7034897190745766939L;//序列号
public RuntimeException() {//构造器1
super();
}
public RuntimeException(String message) {//构造器2
super(message);
}
public RuntimeException(String message, Throwable cause) {//构造器3
super(message, cause);
}
public RuntimeException(Throwable cause) {//构造器4
super(cause);
}
protected RuntimeException(String message, Throwable cause,
boolean enableSuppression,
boolean writableStackTrace) {//构造器5
super(message, cause, enableSuppression, writableStackTrace);
}
}