概述
当方法内部发生一项错误时,该方法会创建一个对象传递给运行时系统(runtime system),这个对象被称为异常对象,包括错误的类型、发生位置。程序状态等一系列信息。
当一个方法抛出异常时,运行时系统会沿着调用栈(call stack)寻找该异常的处理方式 。
下图中,调用栈以下的方法调用了上面的方法,层层嵌套,一共四层:
调用第三个方法时抛出了一个异常,运行时系统就会沿着调用栈反向寻找该异常的处理程序,当该异常类型与某个异常处理程序声明的异常类型一致时。系统就将该异常交给它处理。
假设系统没能找到合适的异常处理程序,系统将会终止。
异常类型
java提供了两种处理异常的方式:
(1) 使用try语句捕获异常并处理。
(2) 使用throwskeyword列出要抛出的异常类型,代表在本方法内不做处理。可是调用该方法的方法必须处理该异常或者继续抛出。
并非全部异常都须要显式处理(这里的处理代表在程序内部捕获或者抛出),比方IOException、SQLException等是必须要处理的。而NullPointerException、ArithmeticException、IndexOutOfBoundsException等能够不作处理。
理解这一点。就要弄清异常的基本分类。
Checked Exception
这类异常是应用程序能够预见并能够恢复的错误。比方。应用程序须要用户输入一个文件名称,然后程序将对这个文件进行读写操作。假如用户输入的文件名称不存在。抛出java.io.FileNotFoundException,应用程序应该捕获这个异常并提醒用户。相似这样的异常就属于checked exception。
除了Error、RuntimeException以及两者的子类,全部异常都属于checked exception。
Error
Error一般来说是应用程序外部引起的异常,应用程序通常不能预见并恢复。比方,程序顺利打开了一个文件,可是因为硬件或者操作系统故障,不能够读取文件里的内容,程序就会抛出java.io.IOError。
Runtime Exception
runtimeexception一般来说是程序内部引起的异常,应用程序通常能够预见并恢复。
这类异常的出现一般暗示程序存在bug。比方,还是文件操作的样例。因为逻辑错误,传入的文件名称为空值,程序就会抛出一个NullPointerException。
尽管能够让程序捕获runtimeexception,但更合适的做法是剔除引起这类异常的bug。
java的异常类层次图例如以下:
异常的捕获
checked exception必须捕获。而unchecked exception的捕获不是必须的。比如:
import java.io.*; import java.util.List; import java.util.ArrayList; public class ListOfNumbers { private List<Integer> list; private static final int SIZE = 10; public ListOfNumbers () { list = new ArrayList<Integer>(SIZE); for (int i = 0; i < SIZE; i++) { list.add(new Integer(i)); } } public void writeList() { try{ // FileWriter的构造方法 throws IOException, checked exception类型,必须捕获 PrintWriter out = new PrintWriter(new FileWriter("OutFile.txt")); for (int i = 0; i < SIZE; i++) { // get(int)方法throws IndexOutOfBoundsException,RuntimeException的子类。unchecked exception类型,不是必须要捕获的 out.println("Value at: "+ i + " = " + list.get(i)); } out.close(); }catch(IOException e){ //捕获IOException ... } } }unchecked exception在一些特殊的情况下也能够选择捕获它,比方上面的程序,如今既要捕获IOException,也要捕获IndexOutOfBoundsException。改写例如以下:
public void writeList() { try{ // FileWriter的构造方法 throws IOException, checked exception类型。必须捕获 PrintWriter out = new PrintWriter(new FileWriter("OutFile.txt")); for (int i = 0; i < SIZE; i++) { // get(int)方法throws IndexOutOfBoundsException。RuntimeException的子类。unchecked exception类型,不是必须要捕获的 out.println("Value at: "+ i + " = " + list.get(i)); } out.close(); }catch(IndexOutOfBoundsException e){ //捕获IndexOutOfBoundsException ... }catch(IOException e){ //捕获IOException ... }假设要同一时候捕获的异常存在继承关系,即某个异常时还有一个异常的子类,必须把父类异常写在子类异常后面,否则会报编译错误。
可是。不管有几个捕获语句,终于至多会进入一个catch语句。
比如:
public class Example { public void test() throws IOException{ throw new IOException(); } public static void main(String args []){ Example example = new Example(); try { example.test(); } catch (IOException e) { System.out.println("捕获了子类异常"); } catch (Exception e) { System.out.println("捕获了父类异常"); } } }上例中,IOException是Exception的子类,假设方法抛出了IOException异常,会进入第一个catch子句,但不会进入第二个catch语句;假设抛出的是非IOException的其它Exception子类异常。则会直接进入第二个catch子句。
也就是说,不会同一时候进入两个catch子句。
从Java SE 7以后,一个catch块能够捕获多个异常。上面的捕获语句可简写为:
catch (IndexOutOfBoundsException | IOException ex) { ... }须要注意的是,这样的情况下,catch的參数(上例中的“ex”)默认是final的。不能够在catch块中对它再次赋值。
不管异常是否发生,try代码块退出后,finally代码块都会运行。经常常使用于释放资源。比如:
public void writeList() { PrintWriter out = null; try{ out = new PrintWriter(new FileWriter("OutFile.txt")); for (int i = 0; i < SIZE; i++) { out.println("Value at: " +i + " = " + list.get(i)); } }catch(IOException e){ ... }finally{ //释放资源 if(out!=null){ out.close(); } } }上例中,有三种情况可导致try代码块退出:
(1)newFileWriter("OutFile.txt")抛出IOException
(2)list.get(i)抛出IndexOutOfBoundsException
(3)无异常抛出,代码运行完成
不管发生了上面的那种情况,运行时系统都会保证finally代码块中的程序运行。
须要注意的是,假设在运行try-catch代码块的时候JVM退出了。或者运行try-catch代码块的线程被中断或者杀死。或者使用了System.exit()函数等。finally代码块有可能不被运行。
带有返回值的函数中使用了try-catch-finally块,且返回值与是否发生异常有关,则应该避免将返回值写在finally块中,因为不管是否会发生异常,都会依照finally块的返回值。而忽略try-catch不论什么地方的返回值。比如:
public int test(){ InputStream in = null; try { File f = new File("F:\test.txt"); in = new FileInputStream(f); return 1; } catch (IOException e) { e.printStackTrace(); return 2; }finally{ try { in.close(); } catch (IOException e) { e.printStackTrace(); } return 3; } }上例中,不管是否会抛出IOException,都不会返回1或2,仅仅会返回3。
try-with-resources语句
在try中声明的一个或多个资源,在程序结束后应该关闭,通常我们是在finally代码块中完成这项工作。
从java 7開始。提供了一种更为简洁有效的写法: try-with-resources语句。
使用形式例如以下:
static String readFirstLineFromFile(String path) throws IOException { try (BufferedReader br = new BufferedReader(new FileReader(path))) { return br.readLine(); } }try-with-resources确保{}内的程序运行完成后自己主动关闭资源,全部实现了java.lang.AutoCloseable接口(java 7新增的接口,java.lang.Closeable的父接口。)的对象都能够当作资源。
throw与throws
捕获异常的前提是有方法抛出了异常。
throwkeyword用于在方法体内部,错误发生的地方抛出异常。如:
public Object pop() { Object obj; if (size == 0) { //栈为空,抛出异常 throw new EmptyStackException(); } obj = objectAt(size - 1); setObjectAt(size - 1, null); size--; return obj; }该方法用于从栈中弹出栈顶元素。可是。假设栈为空就不能进行这项操作。所以就会抛出EmptyStackException异常。
当其它方法调用pop()方法时。就应该考虑到pop()可能会抛出的异常,假设假设pop()抛出的UncheckedException,能够不做额外的处理;假设pop()抛出的是checked Exception则必须进行处理,能够用try-catch捕获,也能够选择在本方法内不做捕获,继续用throwskeyword抛出。如:
public void callPop() throws EmptyStackException { ... pop(); //该方法可能会抛出EmptyStackException ... }实际上,一个异常非常多时候是因为还有一个cause异常引起的。因为cause 自身也会有 cause。依此类推,就形成了链式异常(Chained Exceptions)。
比如:
try {
} catch(IOException e) { //捕获到IOException时,抛出还有一个异常
throw new SampleException("Other IOException", e);
}
Throwable有一种造函数能够接受Throwable类型的參数作为引起该异常的cause,Throwable类的initCause(Throwable)、getCause()能够设置cause信息、获取cause信息。
java异常拾遗
时间: 2024-10-10 09:17:19
java异常拾遗的相关文章
Java HashMap拾遗
Java HashMap拾遗 @author ixenos 零碎知识 尽量返回接口而非实际的类型,如返回List.Set.Map而非ArrayList.HashSet.HashMap,便于更换数据结构,而客户端代码不用改变.这就是针对抽象编程 Map.entrySet 方法返回Map映射的 Set 视图Set<Map.Entry<K,V>>,维护entry键值对 该 set 受Map映射支持,所以对Map映射的更改可在此 set 中反映出来,反之亦然! 如果对该 set 进行迭代的
java 异常的捕获及处理
在没有异常处理的程序中如果要回避异常,需要使用大量的判断语句,配合所想到的错误状况来捕捉程序中可能发生的错误.但是这样势必会导致程序运行效率降低.java异常处理机制具有易于使用,可自定义异常类,处理抛出的异常的同时,又不会降低程序运行效率等优点.因而在java程序设计时,应充分的利用异常处理机会,以增进程序的稳定性及效率.1.异常处理示例及基本格式: package javaBasics; public class test5 { public static void main(String[
2.Java异常学习
1.Java异常的概念 异常的例子 1.除法就是一个需要捕获异常的例子,除数又可能是0 异常处理的基本流程如下 一旦发生异常,就使得程序不按照原来的流程继续的运行下去 a.程序抛出异常 try{ throw new Exception(); } b.捕获异常 catch(Exception e){ //异常处理程序 } c.finally代码块 必须注意的是:在finally块中不能抛出异常. finally{ //一定会被执行 //除非catch中有System.exit(0);会推出Java
【译】常见 Java 异常解释(恶搞版)
常见 Java 异常解释:(译者注:非技术角度分析.阅读有风险,理解需谨慎o(╯□╰)o) java.lang ArithmeticException 你正在试图使用电脑解决一个自己解决不了的数学问题,请重新阅读你的算术表达式并再次尝试. ArrayIndexOutOfBoundsException 请查看 IndexOutOfBoundsException.不同之处在于这个异常越界的元素不止一个. ArrayStoreException 你已用光了所有数组,需要从数组商店中购买更多的数组. C
java异常面试常见题目
在Java核心知识的面试中,你总能碰到关于 处理Exception和Error的面试题.Exception处理是Java应用开发中一个非常重要的方面,也是编写强健而稳定的Java程序的关键,这自然使它成为面试题中的常客.关于Java中Error和Exception的面试题目多是关于Exception和Error的概念,如何处理Exception,以及 处理Exception时需要遵守的最佳实践等等.尽管关于多线程.垃圾回收.JVM概念和面向对象设计等方面的问题依然主宰着这类面试,你仍然需要为回答
Java异常打印输出中常见方法的分析
Java异常是在Java应用中的警报器,在出现异常的情况下,可以帮助我们程序猿们快速定位问题的类型以及位置.但是一般在我们的项目中,由于经验阅历等多方面的原因,依然有若干的童鞋在代码中没有正确的使用异常打印方法,导致在项目的后台日志中,没有收到日志或者日志信息不完整等情况的发生,这些都给项目埋下了若干隐患.本文将深入分析在异常日志打印过程中的若干情况,并给出若干的使用建议. 1. Java异常Exception的结构分析 我们通常所说的Exception主要是继承于Throwable而来,可以参
Java异常总结
http://blog.csdn.net/hguisu/article/details/6155636 [-] 1 引子 2JAVA异常 4处理异常机制 1 捕获异常trycatch 和 finally try-catch语句 trycatch-finally语句 try-catch-finally 规则异常处理语句的语法规则 trycatchfinally语句块的执行顺序 2 抛出异常 throws抛出异常 使用throw抛出异常 4 Throwable类中的常用方法 5Java常见异常 ru
Java异常初步
所谓异常就是程序在运行时出现的不正常情况; 1.异常的体系: Throwable: 1) Error:通常指JVM出现重大问题如:运行的类不存在或者内存溢出等,这种异常是程序员无法处理的 2) Exception:在运行时运行出现的一些情况,可以通过try,catch,finally处理.比如在计算除法时把除数置0,参数传值是类型不符等. Java异常其实是对不正常情况的一种描述,并将其封装成对象 Java在 设计异常体系时,将容易出现的异常情况都封装成了对象 下面的代码在运行时会将除数置0,在
Java 异常分类
1.java异常层次结构: 粉红色的是已检查异常(checked exceptions),其必须被 try{}catch语句块所捕获,或者在方法签名里通过throws子句声明.已检查异常必须在编译时被捕捉处理,命名为 CHecked Exception 是因为Java编译器要进行检查,Java虚拟机也要进行检查,以确保这个规则得到遵守. 绿色的是未检查异常(unchecked exceptions),需要程序员自己分析代码决定是否捕获和处理,比如 空指针,被0除... 声明为Error的,属于严