一、基础知识
处理异常,java提供了一个优秀的解决方案:异常处理机制。
java把异常当作对象来处理,所有的异常都是由Throwable继承而来,但在下一层立即分解为两个分支:Error和Exception。
java异常体系结构图如下:
Error类:这类异常由java虚拟机生成并抛出,大多数错误与代码编写者无关,不能被程序员通过代码来处理。发生这种异常时,java虚拟机一般会选择关闭线程。Error异常很少出现,所以我们更应该关注Exception分支下异常。
Exception类:这类异常通常可以被程序处理,也是我们需要关注的重点。
根据javac对异常处理的要求,我们可以将异常分为两类:
非受查异常:java语言规范将派生于Error类或RuntimeException类的所有异常称为非受查异常。javac在编译时,不会提示和发现这类异常,不要求在程序中处理这些异常。这样的异常多半是代码写的有问题,比如除零、数组越界、空指针异常等。
受查异常:除了Error类或RuntimeException类的所有异常。javac在编译时,会检查这类异常,要么通过try-catch语句进行捕获,要么通过throws语句进行抛出,否则编译不通过。
需要明确的是受查和非受查是对于javac而言的,非受查异常为编译器不要求强制处理的异常,受查异常则是编译器必须处理的异常。
二、异常处理机制
异常处理机制的本质是抛出异常和捕获异常。
2.1、抛出异常
有些异常,我们不知道该如何处理或者说交给调用者处理更好。我们就需要将这种类型的异常抛出,交给上一级去处理,或者可以继续抛出,交给更高一级的调用者去处理。
抛出异常有两个关键字:throw和throws
throws:抛出方法中可能导致的异常,这个异常并不一定发生。这有利于调用者及时处理这些可能发生的异常,保护自己的程序。方法中抛出的所有受查异常,必须通过throws子句抛出,否则会导致编译错误。
语法:
public void method throws EOFException,FileNotFoundException,...{ //method body }
【示例】
public class AppTest extends TestCase { @Test public void test() { try { checkedTest(); } catch (FileNotFoundException e) { System.out.println("未找到文件!"); } } public void checkedTest() throws FileNotFoundException { FileInputStream fileIn = new FileInputStream("E:\a.txt"); System.out.println("FileInputStream抛出受查异常"); } }
throw:抛出明确的异常,throw后面的任何语句不会被执行,
语法:
throw new Exception();
【示例】
public class AppTest extends TestCase { @Test public void test() { throwTest(null); } public void throwTest(String input) { if (input == null) { throw new NullPointerException(); } } }
2.2、捕获异常
语法:
try{ //可能出现异常的代码 }catch(SQLException e){ }catch(Exception e){ }finally{ }
这里有几点需要注意:
1)如果代码可能抛出多种异常,相应的我们也要使用多个catch子句进行捕获。当异常发生时,每个catch子句会被依次检查,当第一个匹配的子句被执行时,捕获结束,其他的子句将不会再检查。所以这里有一个重要原则:先子类后父类
2)finally子句是可选项,可有可无。无论出不出现异常,finally都会在try/catch之后执行。
- 不要再finally里使用return,会覆盖前面的返回值。
- 不要在finally里抛出异常,会抑制前面抛出的异常。
- 尽量不要再finally里做其他事,finally仅仅用于释放资源最合适。
- 尽量将所有的return写在方法的最后,不要写在try/catch/finally中。
三、异常分析
【示例】
public class Java8Tester { public static void main(String args[]) { throwTest(null); } public static void throwTest(String input) { if (input == null) { throw new NullPointerException(); } } }
结果:
Exception in thread "main" java.lang.NullPointerException//异常线程,异常类型 at com.my.Java8Tester.throwTest(Java8Tester.java:16)//异常抛出点 at com.my.Java8Tester.main(Java8Tester.java:11)//调用方法