JAVA高级特性(一)异常处理
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 class AutoCloseTest{ public static void main(String[] args)throws IOException{ //有final修饰的资源 final BufferedReader br = new BufferedReader( new FileReader("AutoCloseTest.java")); //没有使用final,但只要不对该变量重新赋值,该变量就是有效的final PrintStream ps = new PrintStream( new FileOutputStream("a.txt")); //只要将两个资源放在try后的圆括号内即可 try(br;ps){ //使用两个资源 System.out.println(br.readLine()); ps.println("庄生晓梦迷蝴蝶"); } } }
使用throws声明抛出异常:
public class ThrowsTest{ public static void main(String[] args)throws Exception{ //因为test()方法声明抛出IOException异常 //所以调用该方法的代码要么处于try...catch块中 //要么处于另一个带throws声明抛出的方法中 test(); } public static void test()throws IOException{ //因为FileInputStream的构造器声明抛出IOException异常 //所以调用FileInputStream的码要么处于try...catch块中 //要么处于另一个带throws声明抛出的方法中 FileInputStream fis = new FileInputStream("a.txt"); } }
使用throw声明抛出异常:
在大部分时候推荐使用Runtime异常,而不使用Checked异常
throw语句抛出的不是异常类,而是一个异常实例,而且每次只能抛出一个异常实例:
public class ThrowTest{ public static void main(String[] args){ try{ //调用声明抛出的Checked异常的方法,要么显示捕获该异常 //要么在main方法中再次声明抛出 throwChecked(-3); }catch(Exception e){ System.out.println(e.getMessage()); } //调用声明抛出Runtime异常的方法既可以显示捕获该异常 //也可不理会异常 throwRuntime(3); } public static void throwChecked(int a)throws Exception{ if(a>0){ //自行抛出Exception异常 //该代码必须处于try块里,或处于带throws声明的方法中 throw new Exception("异常"); } } public static void throwRuntime(int a){ if(a>0){ //自行抛出RuntimeException异常,既可以显示捕获该异常 //也可不理会,把该异常交给该方法调用者处理 throw new RuntimeException("异常"); } } }
自定义异常:
定义异常类时通常需要提供两个构造器:
①一个是无参的构造器;
②另一个是带一个字符串参数的构造器。(也就是异常对象的getMessage()方法的返回值)
public class AuctionException extends Exception{ //无参的构造器 public AuctionException(){} //带一个字符串参数的构造器 public AuctionException (String msg){ super(msg); } }
catch和throw同时使用:
当一个异常出现时没,单靠某个方法无法完全处理该异常,必须由几个方法协作才可完全处理该异常。
在异常出现的当前方法中,程序只对异常进行部分处理,还有些处理需要在该方法的调用者中才能完成,所以应该再次抛出异常,让该方法的调用者也能捕获到异常。
public class AuctionTest{ //因为该方法中显示抛出了AuctionException异常 //所以此处需要声明抛出AuctionException异常 public void bid(String bidPrice)throws AuctionException{ try{ }catch(Exception e){ //此处完成本方法中科院对异常执行的修复处理 //此处仅仅是在控制台打印异常的跟踪栈信息 e.printStackTrace(); //再次抛出自定义异常 throw new AuctionException("出错"); } } public static void main(String[] args){ AuctionTest at = new AuctionTest(); try{ at.bid("df"); }catch(AuctionException ae){ //再次捕获到bid()方法中的异常,并对异常进行处理 System.err.println(ae.getMessage()); } } }

浙公网安备 33010602011771号