在Java程序设计语言中,异常对象都是派生于throwable类的一个实例。
所有的异常都是由Throwable继承而来,但下一层次立即分为两个分支: Error和 Exception。
Error类层级结构描述了Java运行时系统的内部错误和资源消耗错误。应用程序不应该抛出这种类型的对象。如果出现了这样的内部错误,除了通知给用户,并尽力使程序安全地终止之外,再也无能为力了。
Exception层次结构有分解为两个分支:一个分支派生于RuntimeException;另一个分支包含其他异常。
由程序错误导致的异常属于RuntimeException;而程序本身没问题,但由于像I/O错误这类问题导致的异常属于其他异常。
RuntimeException异常,例如:
错误的类型转换;
数组访问越界;
访问null指针;
Java语言规定派生于Error类或RuntimeException类的所有异常称为非受查(unchecked)异常。所有其他的异常称为受查(checked)异常。
编译器将核查是否为所有的受查异常提供了异常处理器。
一个方法必须声明所有可能抛出的受查异常,而非受查异常要么不可控制(Error),要么就应该避免发生(RuntimeException)。如果方法没有声明所有可能发生的受查异常,编译器就会发生一个错误消息。
四、合并catch子句
try {
InputStream in =new FileInputStream(f);
in.read();
} catch (FileNotFoundException | UnknownHostException e) {
} catch(IOException e){
}
在Java SE7 之后,可以使用合并catch子句。只有当捕获的异常类型彼此之间不存在子类关系时才需要这个特性。
而 FileNotFondException继承与IOException,所以不能和IOException合并在一起:
五、再次抛出异常
try{
access the database
}catch(SQLException e){
Throwable se = new ServletException("database error");
se.initCause(e);
throw se;
}
强烈建议使用包装技术,让用户抛出子系统的高级异常,而不会丢失原始异常细节。
六、关于try/catch 和 try/finally 语句块
强烈建议解耦和 try/catch 和 try/finally 语句块 。这样可以提高代码的清晰度。如:
try{
try{
code...
}finally{
in.close();
}
}catch{
show error message.
}
七、带资源的try语句
带资源的try语句的最简单的形式为:
try(Resource res = ...)
{
work with res
}
假设资源属于一个实现了AutoCloseable 接口的类。AutoCloseable 接口有一个方法:void close() throws Exception
try 块退出时,会自动调用res.close(),下面是一个典型的例子:
public static void main(String[] args) {
String filePath = "F:\\stacktrace\\AutoCloseableTest.java";
try{
try (Scanner in = new Scanner(new FileInputStream(filePath), "UTF-8")){
while(in.hasNext()){
System.out.println(in.next());
}
}
}catch(FileNotFoundException e){
e.printStackTrace();
}
}
可以指定多个资源
public static void autoCloseTest02(String filePath,String outFilePath){
try {
try (Scanner in = new Scanner(new FileInputStream(filePath), "UTF-8");
PrintWriter out = new PrintWriter(outFilePath))
{
while(in.hasNext()){
out.println(in.next().toUpperCase());
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}