迷迷糊糊的异常

Posted mgblogs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了迷迷糊糊的异常相关的知识,希望对你有一定的参考价值。

一、异常与记录日志

技术图片
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.logging.Logger;

class LoggingException extends Exception
    private static Logger logger = Logger.getLogger("LoggingException");
    public LoggingException() 
        StringWriter trace = new StringWriter();
        printStackTrace(new PrintWriter(trace));
        logger.severe(trace.toString());
    

public class Demo6 
    public static void main(String[] args) 
        try 
            throw new LoggingException();
        catch(LoggingException e) 
            System.err.println("Caught " + e);
        
    
View Code

 

输出结果:

技术图片

 

二、栈轨迹

技术图片
public class Demo7 

    void f1() throws Exception 
        throw new Exception();
    
    void f2()throws Exception  f1(); 
    void f3()throws Exception  f2(); 
    public static void main(String[] args) 
        // TODO Auto-generated method stub
        try 
            Demo7 d = new Demo7();
            d.f3();
        catch(Exception e) 
            for(StackTraceElement s : e.getStackTrace()) 
                System.out.println(s);
            
        
    

View Code

 

输出结果:

技术图片

 

结果说明:getStackTrace()此方法返回轨迹栈中的元素StackTraceElement所构成的数组,轨迹栈中的每一栈帧即为一层函数的调用。(同虚拟机栈中的栈帧)。

三、重新抛出异常

实例一:异常对象的消息内容与在那一层方法处理异常无关

技术图片
public class Demo8 

    void f() 
        try 
            throw new Exception("My Exception");
        catch(Exception e) 
            e.printStackTrace();
        
    
    void g()  f(); 
    public static void main(String[] args) 
        // TODO Auto-generated method stub
        Demo8 d = new Demo8();
        d.f();
    

View Code

 

输出结果:

技术图片

 

结果说明:异常对象消息内容和异常处理地点的无关性,轨迹栈的栈底永远都是main();

 

实例二:fillInStackTrace()重新抛出带有新消息的异常

技术图片
public class Demo9 
    
    void f() throws Exception 
        throw new Exception("from f()");
    
    //抛出原来的异常
    void g() throws Exception 
        try 
            f();
        catch(Exception e) 
            System.out.println("g(), e.printStackTrace():");
            e.printStackTrace(System.out);
            throw e;
         
    
    //将原来的异常填入当前调用栈消息,并覆盖原有消息
    void h() throws Exception 
        try 
            f();
        catch(Exception e) 
            System.out.println("f(), e.printStackTrace():");
            e.printStackTrace(System.out);
            //这里throw类似方法调用,fillInStackTrace()返回Throwable类
            throw (Exception)e.fillInStackTrace();
         
    
    public static void main(String[] args) 
        // TODO Auto-generated method stub
        Demo9 d = new Demo9();
        try 
            d.g();
        catch(Exception e) 
            System.out.println("main() e.printStackTrace()");
            e.printStackTrace(System.out);
        
        
        try 
            d.h();
        catch(Exception e) 
            System.out.println("main() e.printStackTrace()"); 
            e.printStackTrace(System.out);
        
    

View Code

 

输出结果:

 技术图片

 

结果说明:fillInStackTrace()方法将当前异常抛出点方法调用栈的信息覆盖原来抛出点调用栈信息。

 

四、异常链

异常链:在捕获一个异常后抛出另外一个异常,并把原始异常的信息保存下来。

使用情形:一般在构造器中处理异常,都会另外再抛出一个异常,因为不想让调用方误以为对象被成功的建立。不过尽量不要编写抛出异常的构造器,编码会比较麻烦,应该让对象尽快安全的被初始化和建立。

 

 

实例一:

技术图片
public class Demo10 

    public static void main(String[] args) 
        // TODO Auto-generated method stub
        Demo10 d = new Demo10();
        try 
            d.test();
        catch(Exception e) 
            e.printStackTrace();
        
    
    
    void test() 
        try 
            int i = 10/0;
        catch(Exception e) 
            throw new RuntimeException(e);
        
    

View Code

 

输出结果:

技术图片

 

结果说明:像这样直接使用构造器接受cause的类,只有Error、Exception、RuntimeException。其它类型需要使用initCause()方法连接。实际上,异常类的绝大部分方法都是从Throwable继承而来的。

 

实例二:

技术图片
import java.io.IOException;

class MyException extends Exception

public class Demo11 

    
    static void test() throws MyException
        try 
            throw new IOException();
        catch(Exception e) 
            MyException m = new MyException();
            m.initCause(e);
            throw m;
        
    
    
    public static void main(String[] args) 
        // TODO Auto-generated method stub
        try 
            test();
        catch(Exception e) 
            e.printStackTrace();
        
    

View Code

 

输出结果:

技术图片

 

 

结果说明:调用initCause()惯例,要么在创建异常的时候马上调用,要么在异常的构造器中调用。

 

实例三:“被检查异常”包装成“不受检查的异常”

 

技术图片
public class Demo13 

    public static void main(String[] args) 
        // TODO Auto-generated method stub
        try 
            test();
        catch(Exception e) 
            e.printStackTrace();
            try 
                throw (Exception)e.getCause();
            catch(Exception e1) 
                System.out.println("getCause():");
                e1.printStackTrace();
            
            
        
    
    
    static void test() 
        try 
            throw new Exception();
        catch(Exception e) 
            throw new RuntimeException(e);
        
    

View Code

 

输出结果:

技术图片

结果说明:getCause()方法望文知意,是用来获取Cause的,并返回Throwable类。

 

五、异常丢失

 实例:

public class Demo12 

    public static void main(String[] args) 
        // TODO Auto-generated method stub
        try 
            throw new RuntimeException();
        finally 
            return;
        
    

 

结果说明:部分代码不会抛出任何异常,但是会有警告:finally模块没有正常编译。

 

六、异常的限制

1、覆盖方法时,只能够抛出基类方法异常说明里的异常。(可以是异常说明里异常的子类)这样不影响某些共用代码。

2、如果继承的或者实现的类,有同名方法,在进行覆盖时,要取throws声明的子集。

3、在进行向上转型时,用基类引用调用方法时要捕获基类此方法的异常,应为编译器根本就不清楚基类引用的实际类型,所以通不过编译。

实例:

 

技术图片
import java.io.IOException;

class A 
    void print() throws IOException 
            System.out.println("A");
            throw new IOException();
    

public class Demo12 extends A

    void print() 
        System.out.println("Demo12");
    
    public static void main(String[] args) 
        // TODO Auto-generated method stub
        try 
            A a = new Demo12();
            a.print();
        catch(Exception e) 
            e.printStackTrace();
        
        
    

View Code

 

 

输出结果:

Demo12

 

以上是关于迷迷糊糊的异常的主要内容,如果未能解决你的问题,请参考以下文章

第十二章 通过异常处理错误

java基础 第十二章(异常处理工具类集合)

第十二章 重新抛出异常与异常链

第十二章 通过异常处理错误

《Java编程思想》笔记 第十二章 通过异常处理错误

《JAVA编程思想》学习笔记——第十二章 通过异常处理错误