1.异常概述
异常:异常就是Java程序运行过程中出现的错误
由来:现实生活的问题在Java程序中可以这样描述,将不正常情况封装成一个对象,
故事:
星期天的早上,天气明朗,风和日丽。我打算自驾游...
a. 我骑车走在山路上,突然山路崩塌了,幸好我即使刹住了车...(天灾,严重的错误)
b. 我出门打算推车出去,我发现轮胎漏气了,我就拿来气筒充气...(我出发前应该事先检查~并且我可以处理)
c. 我吹着口哨在林荫小道形式,突然发现了刘亦菲~我看直了眼,不小心翻车了...(程序运行时发生异常,事先不能预料)
Error:
对应a情况,一般都是jvm发生错误StackOverlowError,OutofMemeryError
一般程序写的有问题,确实内存不够用
Exception:
- 编译期异常:对应b情况。除了RuntimeException及其子类,都是编译期异常。(我们应该进行异常处理)
- 运行时异常:对应c情况,RuntimeException及其子类,就是运行时异常。一般是程序的逻辑有问题:不推荐进行异常处理,而应该修改代码逻辑。
常见异常:
IndexOutofBoundsException,NullPointerException, ClassCastException, StackOverflowError, ParseException...
举例:
int a=2; int b=0;
Sout(a/b);// ArithmeticException
2.jvm的默认处理:
a:先打印出出现错误的线程名称,异常的类名,异常的原因。打印出异常发生的位置(调用栈的信息)
b:终止程序。(主要是这点不好)
3.处理方式:
a:try_catch_finally
b:throw 把问题抛给别人
原则:如果该功能内部可以将问题处理,用try,如果处理不了,交给调用者处理,用throws。
区别:
后续程序需要继续用try
后续程序不需要继续运行用throws
注意事项:main方法不能再往上抛出异常,否则就会抛给JVM,直接调用默认处理。在main方法中只能用 try{} catch 来处理异常
try{
可能发生错误的代码
}
catch(异常类名 异常对象名){
对异常处理
}
finally{
释放资源
}
try_catch_finally标准格式:
try{ 可能发生错误的代码 } catch(异常类名 异常对象名){ 对异常处理 } finally{ 释放资源 }
【注意事项】:
1.try语句块里面的的代码越少越好,最好只有可能发生异常的代码
2.catch里面必须有内容,哪怕是给出一个简单的提示
3.Java的try语句块中只能抛出0或1个异常,一旦抛出异常,try语句后面的错误就不被执行
4.JVM将错误信息封装成一个对象后,会从上到下一次匹配catch语句,找到对应的处理分支
5.如果异常没有子父类关系,异常谁先谁后无关紧要。
6.如果异常有子父类关系,那么子类一定在父类之前
7.Jdk7的新特性,不能在一个分支中出现子父类关系
4.一个异常处理的流程:
先执行try语句块里面的代码
如果没有发生错误,执行finally语句块里面的代码,执行后面的代码
如果发生了错误,JVN会把异常封装成对象,然后和catch语句进行匹配,执行对应的catch语句,执行finally语句块里面的代码,执行后面的代码
5.多种异常:
a.每个异常都进行单独处理 (不好)
b.多个异常一起处理:一旦try里面出了问题,就会在这里把问题抛出去,然后和catch里面的问题进行匹配,一旦有匹配的,就执行catch里面的处理,然后结束try-catch
执行后面的语句
格式:
try{
}
catch{
}
catch{
}
finally
{
}
c.Jdk7的新特性(多种异常处理方式一致)
注意:这个方法虽然简洁,但是也不够好
A:处理方式是一致的。(实际开发种,好多时候就是针对同类型问题给出同个处理
B:多个异常间必须是同级关系
try{
}
catch(异常名1|异常名2|....变量){
}
6.编译期异常和运行时异常
运行时异常:无论是否会发生异常,无需显示处理,编译就能通过(不推荐使用异常处理,而应该修改代码逻辑(if-else等)
编译时异常:无论是否会发生异常,都需要显示处理,否则无法通过编译.(异常处理的情况)
7.异常的体系结构
【注解】:
1. 粉红色的是受检查的异常(checked exceptions),其必须被 try{}catch语句块所捕获,或者在方法签名里通过throws子句声明.受检查的异常必须在编译时被捕捉处理,命名为 Checked Exception 是因为Java编译器要进行检查,Java虚拟机也要进行检查,以确保这个规则得到遵守.
2. 绿色的异常是运行时异常(runtime exceptions),需要程序员自己分析代码决定是否捕获和处理,比如 空指针,被0除...
3. 而声明为Error的,则属于严重错误,如系统崩溃、虚拟机错误、动态链接失败等,这些错误无法恢复或者不可能捕捉,将导致应用程序中断,Error不需要捕捉。
需要了解的方法:
String getMessage()
获取异常信息,返回字符串。
获取异常类名和异常信息,返回字符串。
System.out.println(e.toString()); //java.text.ParseException: Unparseable date: "2019/05/23 16:00:00"
void printStackTrace()
获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void。
e.printStackTrace(); //java.text.ParseException: Unparseable date: "2019/05/23 16:00:00" //at java.text.DateFormat.parse(DateFormat.java:366) //at Exception.Exercise.main(Exercise.java:15)
// void printStackTrace(PrintStream s)
通常用该方法将异常内容保存在日志文件中,以便查阅。
7.finally
1.特点:被fianlly控制的语句体一定会执行
【注意】:如果执行到finally之前,jvm退出了,就不能执行了。(System.exit(0)
2.作用:用于释放资源,在IO流操作和数据库操作种会见到
3.异常格式变形:
try...catch...finally
try...catch...
try...catch...catch...
try...catch...catch...fianlly
try...finally
4.面试题:
1:final,finally,finalize的区别?
final: 最终的
修饰类:该类不能被继承
修饰方法:该方法不能被重写
修饰变量:自定义常量
finally:
finally子句用于释放资源的,放在finally中代码一定会被执行(执行finally语句之前,JVM退出)
finalize:
Object类中的方法。用于垃圾回收
2:如果在catch里面有return,请问finally还执行吗?如果执行,在return前还是后
会。 前面。return是最后一步,返回结果
准确的说应该是在中间,但面试时,答:前。