Java中的异常类型
Java从Throwable直接派生出Exception和Error。其中Exception是可以抛出的基本类型,在Java类库、方法以及运行时故障中都可能抛出Exception型异常;Error表示编译时和系统错误。异常类的结构层次图如下:
所有的RuntimeException类及其子类的实例被称为Runtime异常;
不是RuntimeException及其子类的异常实例则被称为Checked异常。
Java如何处理异常
java7新增的多异常捕获:
try{
}catch (NumberFormatException |ArithmeticException ie){//捕获多异常时,异常变量默认有final修饰,下面代码出错
ie = new ArithmeticException("test");
}catch(Exception e){//捕获一种类型的异常时,异常变量没有final修饰,下面代码正确
e = new RuntimeException("test");
}
访问异常信息:
getMessage():返回该异常的详细描述字符串
printStackTrance():将该异常的跟踪栈信息输出到标准错误输出
printStackTrance(PrintStream s):将该异常的跟踪栈信息输出到指定输出流
getStackTrace():返回该异常的跟踪栈信息
使用finally回收资源:
当Java程序执行try、catch块时遇到了return或throw语句,这两个语句会导致该方法立即结束,但是系统会先去寻找该异常处理流程是否包含finally方法。若有,执行finally方法。
若finally有return语句,则导致try、catch语句的return失效。
注意:除非调用了退出虚拟机的方法(System.exit(0)),否则不管在try块、catch块中执行怎样的代码,异常处理的finally块总会被执行。
Java9增强的自动关闭资源的try语句:
Closeable是AutoCloseable的子接口,可以被自动关闭的资源类要么实现AtuoCloseable接口,要么实现Closeable接口,Closeable接口里的close()方法声明抛出了IOException,因此它的实现类在实现close()方法时只能声明抛出IOException或其子类;AutoCloseable接口里的close()方法声明抛出了Exception,因此它的实现类在实现close()方法时可以声明抛出任何异常。
public classAutoCloseTest{public static voidmain(String[] args)throwsIOException{//有final修饰的资源
final BufferedReader br = newBufferedReader(new FileReader("AutoCloseTest.java"));//没有使用final,但只要不对该变量重新赋值,该变量就是有效的final
PrintStream ps = newPrintStream(new FileOutputStream("a.txt"));//只要将两个资源放在try后的圆括号内即可
try(br;ps){//使用两个资源
System.out.println(br.readLine());
ps.println("庄生晓梦迷蝴蝶");
}
}
}
使用throws声明抛出异常:
public classThrowsTest{public static void main(String[] args)throwsException{//因为test()方法声明抛出IOException异常//所以调用该方法的代码要么处于try...catch块中//要么处于另一个带throws声明抛出的方法中
test();
}public static void test()throwsIOException{//因为FileInputStream的构造器声明抛出IOException异常//所以调用FileInputStream的码要么处于try...catch块中//要么处于另一个带throws声明抛出的方法中
FileInputStream fis = new FileInputStream("a.txt");
}
}
使用throw声明抛出异常:
在大部分时候推荐使用Runtime异常,而不使用Checked异常
throw语句抛出的不是异常类,而是一个异常实例,而且每次只能抛出一个异常实例:
public classThrowTest{public static voidmain(String[] args){try{//调用声明抛出的Checked异常的方法,要么显示捕获该异常//要么在main方法中再次声明抛出
throwChecked(-3);
}catch(Exception e){
System.out.println(e.getMessage());
}//调用声明抛出Runtime异常的方法既可以显示捕获该异常//也可不理会异常
throwRuntime(3);
}public static void throwChecked(int a)throwsException{if(a>0){//自行抛出Exception异常//该代码必须处于try块里,或处于带throws声明的方法中
throw new Exception("异常");
}
}public static void throwRuntime(inta){if(a>0){//自行抛出RuntimeException异常,既可以显示捕获该异常//也可不理会,把该异常交给该方法调用者处理
throw new RuntimeException("异常");
}
}
}
自定义异常:
定义异常类时通常需要提供两个构造器:
①一个是无参的构造器;
②另一个是带一个字符串参数的构造器。(也就是异常对象的getMessage()方法的返回值)
public class AuctionException extendsException{//无参的构造器
publicAuctionException(){}//带一个字符串参数的构造器
publicAuctionException (String msg){super(msg);
}
}
catch和throw同时使用:
当一个异常出现时没,单靠某个方法无法完全处理该异常,必须由几个方法协作才可完全处理该异常。
在异常出现的当前方法中,程序只对异常进行部分处理,还有些处理需要在该方法的调用者中才能完成,所以应该再次抛出异常,让该方法的调用者也能捕获到异常。
public classAuctionTest{//因为该方法中显示抛出了AuctionException异常//所以此处需要声明抛出AuctionException异常
public void bid(String bidPrice)throwsAuctionException{try{
}catch(Exception e){//此处完成本方法中科院对异常执行的修复处理//此处仅仅是在控制台打印异常的跟踪栈信息
e.printStackTrace();//再次抛出自定义异常
throw new AuctionException("出错");
}
}public static voidmain(String[] args){
AuctionTest at= newAuctionTest();try{
at.bid("df");
}catch(AuctionException ae){//再次捕获到bid()方法中的异常,并对异常进行处理
System.err.println(ae.getMessage());
}
}
}