java异常处理机制
- java中所有错误的超类为:Throwable。其下有两个子类:Error和Exception
- Error的子类描述的都是系统错误,比如虚拟机内存溢出等。
- Exception的子类描述的都是程序错误,比如空指针,下表越界等。
- 通常我们程序中处理的异常都是Exception。
try-catch
package exception;
/**
* 异常处理机制中的try-catch
* 语法:
* try{
* 代码片段...
* }catch(XXXException e){
* 出现错误后的补救措施(B计划)
* }
*/
public class TryCatchDemo {
public static void main(String[] args) {
System.out.println("程序开始了...");
/*
try{}语句块不能单独写,后面要么跟catch语句块要么跟finally语句块
异常处理机制关注的是:明知道程序可能出现某种错误,但是该错误无法通过修改逻辑
完全规避掉时,我们会使用异常处理机制,在出现该错误是提供一种补救办法。
凡是能通过逻辑避免的错误都属于bug!就应当通过逻辑去避免!
*/
try {
// String str = null;
// String str = "";
String str = "a";
/*
若str=null的情况
当JVM执行到下面代码时:str.length()会出现空指针,此时虚拟机就会根据该情况
实例化一个对应的异常实例出来,即:空指针异常实例 NullPointerException实例
然后将程序从一开始执行到报错这句话的过程设置到该异常实例中,此时该异常通过
类型名字可以表达出现了什么错误,并将来可以通过输出错误信息来得知错误出现在那里
虚拟机会将该异常抛出
当某句代码抛出了一个异常时,JVM会做如下操作:
1:检查报错这句话是否有被异常处理机制控制(有没有try-catch)
如果有,则执行对应的catch操作,如果没有catch可以捕获该异常则视为没有
异常处理动作
2:如果没有异常处理,则异常会被抛出当当前代码所在的方法之外由调用当前方法的
代码片段处理该异常
*/
System.out.println(str.length());//抛出空指针异常
System.out.println(str.charAt(0));
System.out.println(Integer.parseInt(str));
/*
当try中某句代码报错后,就会跳出try执行下面对应的catch块,执行后就会
退出catch继续向后执行。因此try语句块中报错代码以下的内容都不会被执行
*/
System.out.println("!!!!!!!!!!!!!!");
// }catch(NullPointerException e){
// //这里实际开发中是写补救措施的,通常也会将异常信息输出便于debug
// System.out.println("出现了空指针,并解决了!");
// }catch(StringIndexOutOfBoundsException e){
// System.out.println("处理字符串下标越界问题!");
// }
/*
当try语句块中可能出现的几种不同异常对应的处理办法相同时,可以采取合并
catch的做法,用同一个catch来捕获这几种可能出现的异常,而执行措施使用
同一个。
*/
}catch(NullPointerException|StringIndexOutOfBoundsException e){
System.out.println("处理空指针或下标越界!");
/*
当catch捕获某个超类型异常时,那么try语句块中出现它类型异常时都可以被这个
catch块捕获并处理。
如果多个catch捕获的异常之间存在继承关系时,一定是子类异常在上超类异常在下
*/
}catch(Exception e){
System.out.println("反正就是出了个错!");
}
System.out.println("程序结束了...");
}
}
finally块
finally块是异常处理机制中的最后一块
- finally可以直接跟在try语句块之后
- finally可以跟在最后一个catch块之后
- fianlly下面不能再定义catch块
特点:
只要程序执行到异常处理机制中(执行到try语句块中),无论try中的代码是否出现异常,finally最终都必定执行
作用:
通常用来执行释放资源这一类操作。例如IO操作完毕后的流关闭。
例
package exception;
/**
* finally块
*/
public class FinallyDemo {
public static void main(String[] args) {
System.out.println("程序开始了");
try {
String str = "null";
System.out.println(str.length());
return;//结束方法,结束前finally还是要执行的
} catch (Exception e) {
System.out.println("出错了");
}finally {
System.out.println("finally中的代码执行了");
}
System.out.println("程序结束了");
}
}
在IO中的应用
package exception;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 异常处理机制在IO中的应用
*/
public class FinallyDemo2 {
public static void main(String[] args) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream("./fos.dat");
fos.write(1);
} catch (IOException e) {
System.out.println("出错了");
} finally {
try {
if(fos!=null) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
自动关闭特性
JDK7之后java推出了一个新特性:自动关闭特性可以更优雅的在异常处理机制中关闭IO
语法
try(
声明并初始化IO对象
){
IO操作
}catch(IOException e){//catch各种IO异常
...
}
例
package exception;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* JDK7之后java推出了一个新特性:自动关闭特性
* 可以更优雅的在异常处理机制中关闭IO
*/
public class AutoCloseableDemo {
public static void main(String[] args) {
//自动关闭特性是编译器认可的,编译后就变成FinallyDemo2的样子
try(
FileOutputStream fos = new FileOutputStream("fos.dat");
){
fos.write(1);
} catch (IOException e) {
e.printStackTrace();
}
}
}