java异常——分析堆栈跟踪元素+使用异常机制的技巧

【0】README

0.1) 本文描述+源代码均 转自 core java volume 1, 旨在理解 java异常——分析堆栈跟踪元素+使用异常机制的技巧 的相关知识;


【1】分析堆栈跟踪元素相关

1.1)堆栈跟踪: 它是一个方法调用过程的列表, 它包含了程序执行过程中方法调用的特定位置;
1.2)调用Throwable 类的 printStackTrace 方法访问堆栈跟踪的文本描述信息;

Throwable t = new Throwable();
ByteArrayOutputStream out = new ByteArrayOutputStream();
t.printStackTrace(out);
String descriptoin = out.toString();

1.3)更灵活的方法是使用 getStackTrace 方法,它会得到 StackTraceElement对象的一个数组, 可以在你的程序中分析这个对象数组:

Throwable t = new Throwable();
StackTraceElement[] frames = t.getStackTTrace() ;
for(StackTraceElement frame : frames )
    analyze frame

1.4)StackTraceElement类:含有能够获得文件名和当前执行的代码行号的方法;同时, 还有能够获得类名和方法名的方法;
1.5)看个荔枝(静态的Thread.getAllStackTrace)方法, 它可以产生所有线程的堆栈跟踪, 下面给出这种方式的具体步骤:

Map<Thread, StackTrace[]> map = Thread.getAllStackTraces();
for(Thread t : map.keySet)
{
    StackTraceElement[] frames = map.get(i);
       analyze frames;
}

这里写图片描述

  • API java.lang.Throwable 1.0
    Throwable(Throwable cause)
    Throwable(String msg, Throwable cause) : 给定的原因构造一个 Throwable 对象;
    Throwable initCause(Throable cause):将这个对象设置为原因。 如果这个对象已经设置为原因, 则抛出异常;返回this 引用;
    Throwable getCause():获得设置为这个对象的原因的异常对象。如果没有设置原因, 则返回 null;
    StackTraceElement[] getStackTrace() : 获得构造这个对象时调用堆栈的跟踪;
    void addSuppressed(Throwable t) : 为这个异常增加一个抑制异常, 这出现在带资源的try 语句中, 其中t 是close方法抛出的一个异常;

  • API lang.Exception
    Exception(Throwable cause)
    Exception(String msg, Throwable cause):用给定的原因构造一个异常对象;

  • API java.lang.RuntimeException
    RuntimeException(Throwable cause)
    RuntimeException(String msg, Throwable cause) : 用给定原因构造一个 RuntimeException 异常;

  • API java.lang.StackTraceELement
    String getFileName(): 返回这个元素运行时对应的源文件名, 如果这个信息不存在, 返回null;
    int getLineNumber(): 返回这个元素运行时对应的源文件行数。如果不存在, 返回-1;
    String getClassName():返回这个元素运行时对应的类的全名;
    String getMethodName():返回这个元素运行时对应的方法名。 构造器名是, 静态初始化器名是 , 这里无法区分同名的重载方法;
    boolean isNativeMethod():如果这个元素运行时在一个本地方法中, 则返回true;
    String toString(): 如果存在的话, 返回一个 包含类名, 方法名, 文件名和行数的格式化字符串;


【2】使用异常机制的技巧

2.1)异常处理不能代替简单的测试:

如以下代码或者是: if(!s.empty()) s.pop();
或者是:
try
{
    s.pop();
}
catch(EmptyStackException e)
{}
  • 我们发现, 调用 isEmpty()的运行时间为 646ms , 而捕获 EmptyStackException 的运行时间为 21739 ms, 所以,我们可以看出, 与执行简单的测试相比, 捕获异常所花费的时间大大超过了前者,
  • 因此使用异常的规则是:只在异常情况下使用异常机制;

2.2)不要过分地细化异常

  • 很多coder 吧每一条语句都分装在一个独立的 try 语句块中;因此, 有必要将整个任务包装在一个try 语句块中,这样, 当任何一个操作出现问题时, 整个任务都可以取消了;

2.3)利用异常层次结构

  • 2.3.1)不要只抛出RuntimeException异常,应该寻找更加适当的子类或创建自己的异常类;
  • 2.3.2)不要只捕获Throwable 异常, 否则,会使代码更难读和维护;
  • 2.3.3)考虑已检查异常与未检查异常的区别。因为已检查异常本身就很庞大, 不要为逻辑错误抛出这些异常;
  • 2.3.4)将一种异常转换为另一种异常时不要犹豫。例如, 在解析某个文件的一个整数时, 捕获 NumberFormatException 异常, 然后将它转换为 IOException 或 MySubSystemException的子类;

2.4)不要压制异常, 在java中, 往往强烈地倾向于关闭异常

  • 如果编写了一个调用另一个方法的方法, 该方法有可能100年才抛出一个异常, 那么编译器会因为没有将这个异常列在throws 表中产生抱怨。 而没有将这个异常列在其中的原因是 编译器将会对所有调用这个方法的方法进行异常处理的考虑, 因此, 应该将这个异常关闭;
public Image loadImage(String s)
{
    try
    {
        code that threatens to throw checked exceptions
    }
    catch(Exception e)
    {}// so there
}
  • 现在, 这段代码就可以通过编译了;

2.5)在检查错误时, 苛刻要比放任好

  • 如, 当栈空时, Stack.pop() 是返回一个 null , 还是抛出一个异常? 我们认为: 在出错的地方抛出一个 EmptyStackException 异常要比在后面抛出一个 NullPointerException 要好;

2.6)不要羞于传递异常

  • 如, FileInputStream 构造器或 readLIne方法, 这些方法就会本能地捕获这些可能产生的异常, 其实, 传递异常要比捕获这些异常更好:
public void readStuff(String filename) throws IOException
{
    InputStream in = new FileInputStream(filename);
    ......
}
  • 让高层次的方法通知用户发生了错误, 或者放弃不成功的命令更加适宜;
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值