异常
异常机制增强了程序的健壮性
异常的继承结构
对异常的两种处理方式
throws关键字上抛异常
在方法声明的位置,使用throws关键字,抛给上一级
public class Demo {
public static void main(String[] args) throws Exception{
System.out.println("main begin");
m1();
System.out.println("main over");
}
public static void m1() throws Exception{
System.out.println("m1 begin");
m2();
System.out.println("m1 over");
}
private static void m2() throws Exception{
System.out.println("m2 begin");
m3();
System.out.println("m2 over");
}
private static void m3() throws Exception{
FileInputStream fileInputStream = new FileInputStream("D:\\asdf.txt");
}
}
/*输出结果:
main begin
m1 begin
m2 begin
Exception in thread "main" java.io.FileNotFoundException: D:\asdf.txt (系统找不到指定的文件。)
*/
结论:如果选择上抛异常,那么只要执行位置出现异常,该位置之后的代码都不会执行
try…catch语句捕获异常
public class Demo {
public static void main(String[] args) {
System.out.println("main begin");
try{
m1();
System.out.println("会执行这里吗?");
}catch (Exception e){
System.out.println("系统找不到目标文件!");
}
System.out.println("main over");
}
public static void m1() throws Exception{
System.out.println("m1 begin");
m2();
System.out.println("m1 over");
}
private static void m2() throws Exception{
System.out.println("m2 begin");
m3();
System.out.println("m2 over");
}
private static void m3() throws Exception{
FileInputStream fileInputStream = new FileInputStream("D:\\asdf.txt");
}
}
/*输出结果是:
main begin
m1 begin
m2 begin
系统找不到目标文件!
main over
*/
结论:try…catch语句中,try是尝试捕获异常,如果改行出现异常,改行后面的语句不会执行,会直接进入catch分支语句中,执行代码。代码结束之后,会正常执行之后的代码,并且不会在JVM中报错
深入try…catch
try后面可以写多个catch语句,每一个精确的异常都可以成一类,方便代码调试。
如果写多个catch语句,那么应该遵循从小到大的原则
public class Demo {
public static void main(String[] args) {
try {
FileInputStream fileInputStream = new FileInputStream("D:\\asdf.txt");
fileInputStream.read();
} catch (FileNotFoundException e) {
System.out.println("系统找不到目标文件!");
} catch (IOException e) {
System.out.println("读取文件失败");
}
}
}
如何选择
如果希望调用者处理,就使用throws抛给上一级,其他使用try…catch
异常对象的常用方法
描述信息
getMessage()方法
NullPointerException e = new NullPointerException("空指针异常");
String msg = e.getMessage();
System.out.println(e);
/*输出结果是:
java.lang.NullPointerException: 空指针异常
*/
打印异常堆栈信息
printStackTrace()方法
try {
FileInputStream fileInputStream = new FileInputStream("D:\\asdf.txt");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
/*输出结果是:
java.io.FileNotFoundException: D:\asdf.txt (系统找不到指定的文件。)
at java.base/java.io.FileInputStream.open0(Native Method)
at java.base/java.io.FileInputStream.open(FileInputStream.java:211)
at java.base/java.io.FileInputStream.<init>(FileInputStream.java:153)
at java.base/java.io.FileInputStream.<init>(FileInputStream.java:108)
at Demo.main(Demo.java:53)
*/
finally关键字
try…catch…finally
public class Demo {
public static void main(String[] args) {
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream("D:\\asdf.txt");
String s = null;
s.toString();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}catch(NullPointerException e){
e.printStackTrace();
}finally {
if(fileInputStream != null){
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
结论:finally语句块通常完成资源的释放/关闭,因为即使try…catch语句中出现异常,finally语句块中的代码也会执行
try…finally
try{
System.out.println("try...");
return;
}finally{
System.out.println("finally...");
}
/*输出结果是:
try...
finally...
*/
先执行try…,再执行finally…最后执行return
try{
System.out.println("try...");
System.exit(0);
}finally{
System.out.println("finally...");
}
/*输出结果是:
try...
*/
退出JVM那么之后任何语句都不会执行了
final,finally,finalize
final
final是一个关键字,final修饰的类无法继承,final修饰的方法无法覆盖
finally
finally也是一个关键字,和try连用,使用在异常处理机制中,finally语句块中的代码最终都会执行
finalize
finalize是一个标识符,finalize()是Object类中的一个方法,作为方法名出现
自定义异常
第一步:编写一个类继承Exception或者RuntimeException
第二步:提供两个构造方法,一个无参构造,一个带有String参数的构造方法
public class Demo {
public static void main(String[] args) throws MyException{
thorw new MyException("用户名不能为空!");
}
}
public class MyException extends Exception {
public MyException() {
}
public MyException(String s) {
super(s);
}
}
/*输出结果是:
Exception in thread "main" MyException: 用户名不能为空!
at Demo.main(Demo.java:52)*
/