Java异常、断言和日志——捕获异常

1.捕获异常:

    要捕获一个异常,必须设置try/catch语句块

    例如:

    try{

    }catch(ExceptionType e){

    }

    如果方法中的任何代码抛出一个在catch字句中没有声明的异常类型,那么这个方法就会立刻退出

    通常,应该捕获那些知道如何处理的异常,而将那些不知道怎么处理的异常继续传递

2.捕获多个异常:

    例如:

    try{

    }catch(FileNotFoundException e){

    }catch(UnknownHostException e){

    }catch(IOException e){

    }

    异常对象可能包含与异常本身相关的信息。要想获得对象的更多信息,可以试着使用

    e.getMessage()得到详细的错误信息

    e.getClass().getName()得到异常对象的实际类型

    在Java SE 7中,同一个catch字句中可以捕获多个异常类型,例如:

    try{

    }catch(FileNotFoundException | UnknownHostException e){

    }

    只有当捕获的异常类型彼此之间不存在子类关系时才需要这个特性

3.再次抛出异常与异常链:

    例如:

    try{

    }catch(SQLException e){

        throw new ServletException("database error:"+e.getMessage());

    }

    还有一种更好的处理方法,并且将原始异常设置为新异常的“原因”

    try{

    }catch(SQLException e){

        Throwable se = new ServletException("database error");

        se.initCause(e);

        throw se;

    }

    当捕获到异常时,就可以使用下面这条语句重新得到原始异常:

    Throwable s = se.getCause();

    再来看一个小细节:

    public void updateRecord() throws SQLException{

        ...

        try{

        }catch(Exception e){

            logger.log(level,message,e);

            throw e;

        }

    }

    在Java SE 7之前,Java编译器查看catch块中的throw语句,然后查看e的类型,会指出这个方法可以抛出任何Exception而不只是SQLException。现在这个问题有所改进。编译器会跟踪到e来自try块。假设这个try块中仅有的已检查异常是SQLException实例,另外,假设e在catch块中未改变,将外围方法声明为throws SQLException就是合法的

4.finally子句:

    不管是否有异常被捕获,finally子句中的代码都被执行

    try语句可以只有finally子句,而没有catch子句

    当finally子句也包含return语句时,将会出现一种意想不到的结果。假设利用return语句从try语句块中退出。在方法返回前,finally子句的内容将被执行。如果finally子句中也有一个return语句,这个返回值将会覆盖原来的返回值

    当finally子句本身抛出异常时,原始的异常将会丢失,转而抛出close方法的异常,如果用之前的模式进行处理就会比较繁琐,也就是需要在finally子句中再写try-catch语句,这个时候就需要下面的写法。

5.带资源的try语句:

    假设资源属于一个实现了AutoCloseable接口的方法的类Java SE 7为这种代码模式提供了一个很有用的快捷方式。AutoCloseable接口有一个方法:

    void close() throws Exception

    另外还有一个Closeable接口,是AutoCloseable接口的子接口,也包含一个close方法,但是抛出的是IOException

    带资源的try语句的最简形式为:

    try(Resource res = ...){}

    try块退出时,会自动调用res.close()。例如:

    try(Scanner in = new Scanner(new FileInputStream("/usr/share/dict/words")),"UTF-8"){

        while(in.hasNext()){

            System.out.println(in.next());

        }

    }

    在存在异常的时候,都会调用in.close()方法,就好像使用了finally块一样

    还可以指定多个资源,例如:

    try(Scanner in = new Scanner(new FileInputStream("..."),"UTF-8");PrintWriter out = new PrintWriter("out.txt")){

        while(in.hasNext())

            out.println(in.next().toUpperCase());

    }

    使用了带资源的try语句块之后,原来的异常会重新抛出,而close方法抛出的异常会被抑制。这些异常将会自动捕获,并且addSuppressed方法增加到原来的异常,可以调用getSuppressed方法,它会得到从close方法抛出并被抑制的异常列表

    同样,带资源的try语句自身也可以有catch和finally子句,这些子句会在关闭资源之后执行

6.分析堆栈轨迹元素:

    堆栈轨迹是一个方法调用过程的列表,它包含了程序执行过程中方法调用的特定位置

    可以使用Throwable类的printStackTrace方法访问堆栈轨迹的文本描述信息

    Throwable t = new Throwable();

    StringWriter out = new StringWriter();

    t.printStackTrace(new PrintWriter(out));

    String description = out.toString();

    也可以使用getStackTrace方法,它会得到StackTraceElement对象的一个数组

    StackTraceElement类含有能够获得文件名和当前执行代码行号的方法,同时,还含有能够获得类名和方法名的方法

    静态的Thread.getAllStackTrace方法,它可以产生所有线程的堆栈轨迹,例如:

    Map<Thread,StackTraceElement[]> map = Thread.getAllStackTrace();

    for(Thread t : map.keySet()){

        StackTraceElement[] f = map.get(t);

    }

7.java.lang.Throwable 1.0:

    Throwable(Throwable cause) 1.4

    Throwable(String message,Throwable cause) 1.4

    用给定的原因构造一个Throwable对象

    Throwable initCause(Throwable cause) 1.4

    将这个对象设置为原因,如果这个对象已经被设置为原因,则抛出一个异常,返回this引用

    Throwable getCause() 1.4

    获得设置为这个对象的原因的异常对象,如果没有,返回null

    StackTraceElement[] getStackTrace() 1.4

    获得构造这个对象时调用堆栈的跟踪

    void addSuppressed(Throwable t) 7

    为这个异常增加一个抑制异常

    Throwable[] getSuppressed() 7

    得到这个异常的所有“抑制”异常

8.java.lang.Exception 1.0:

    Exception(Throwable cause) 1.4

    Exception(String message,Throwable cause)

    用给定的原因构造一个异常对象

9.java.lang.RuntimeException 1.0:

    RuntimeException(Throwable cause) 1.4

    RuntimeException(String message,Throwable cause) 1.4

    用给定的原因构造一个RuntimeException对象

10.java.lang.StackTraceElement 1.4:

    String getFileName()

    返回这个元素运行时对应的源文件名。

    int getLineNumber()

    返回这个元素运行时对应的源文件行数

    String getClassName()

    返回这个元素运行时对应的类完全限定名

    String getMethodName()

    返回这个元素运行时对应的方法名

    boolean isNativeMethod()

    如果这个元素运行时在一个本地方法中,则返回true

    String toString()

    如果存在的话,返回一个包含类名、方法名、文件名和行数的格式化字符串

猜你喜欢

转载自blog.csdn.net/qq_38386085/article/details/80887570