Java 中的链式异常

原文:https://www.studytonight.com/java/chained-exception-in-java.php

在 JDK 1.4 中,链式异常被添加到 Java 中。此功能允许您将一个异常与另一个异常相关联,即一个异常描述另一个异常的原因。例如,考虑一种情况,其中一个方法由于试图除以零而抛出一个算术异常,但是异常的实际原因是一个导致除数为零的输入/输出错误。该方法只会向调用方抛出算术异常。所以打电话的人不会知道异常的真正原因。链式异常用于这种情况。

两个新的构造器和两个新的方法被添加到 Throwable 类中,以支持链式异常。

  1. 可投掷(可投掷原因)
  2. 可投掷(弦弦,可投掷原因)

在第一个构造器中,参数原因指定了异常的实际原因。在第二种形式中,它允许我们以字符串形式添加异常描述,并说明异常的实际原因。

getCause()initCause() 是添加到可投掷类的两个方法。

  • getCause() 方法返回与当前异常相关联的实际原因。
  • initCause() 通过调用异常来设置底层原因(异常)。

是时候举个例子了!

让我们借助一个例子来理解链式异常,这里,程序抛出了一个算术异常,但是导致异常的真正原因是 IOException。我们使用 initCause()方法设置异常的原因。

import java.io.IOException;

public class ChainedException
{
    public static void divide(int a, int b)
    {
      if(b == 0)
      {
        ArithmeticException ae = new ArithmeticException("top layer");
        ae.initCause(new IOException("cause"));
        throw ae;
      }
      else
      {
        System.out.println(a/b);
      }
    }

    public static void main(String[] args)
    {
      try 
      {
        divide(5, 0);
      }
      catch(ArithmeticException ae) {
        System.out.println( "caught : " +ae);
        System.out.println("actual cause: "+ae.getCause());
      }
    }
}

捕获:java.lang.ArithmeticException:顶层实际原因:java.io.IOException:原因

例子

让我们再看一个例子来理解链异常,这里抛出了 NumberFormatException,但是异常的实际原因是一个空指针异常。

  public class ChainedDemo1
{ 
  public static void main(String[] args) 
  { 
    try
    { 

      NumberFormatException a = new NumberFormatException("====> Exception"); 

      a.initCause(new NullPointerException("====> Actual cause of the exception")); 

      throw a; 
    } 

    catch(NumberFormatException a) 
    { 

      System.out.println(a); 
      System.out.println(a.getCause()); 
    } 
  } 
}

chained-example

异常传播

在 Java 中,异常是从栈顶抛出的,如果异常没有被捕获,它就被放在栈底,这个过程一直持续到到达栈底并被捕获。这就是所谓的异常传播。默认情况下,未检查的异常会在被调用的链中转发。

例子

在本例中,方法 a2 调用的方法 a1 出现异常,方法 a3 调用的方法 a2 出现异常。方法 a3()包含在 try 块中,以提供安全保护。我们知道方法 a1 将引发异常,但在方法 a3()中处理。这称为异常传播。

 class ExpDemo1{ 
  void a1() 
  { 
    int data = 30 / 0; 
  } 
  void a2() 
  { 
    a1();  
  } 
  void a3() 
  { 
    try { 
      a2();
    } 
    catch (Exception e) 
    { 
      System.out.println(e); 
    } 
  } 

  public static void main(String args[]) 
  { 
    ExpDemo1 obj1 = new ExpDemo1(); 
    obj1.a3(); 
  } 
}

Java . lang . arithmeticexception:/by zero

例子

让我们再举一个例子,这里程序从方法 m1()抛出一个 IOException,它在 n1()内部被调用。方法 m1()引发的异常由方法 n1()处理。

 import java.io.IOException; 
class Demo{ 
  void m1() throws IOException
  { 
    throw new IOException("device error"); 
  } 
  void n1() throws IOException
  { 
    m1(); 
  } 
  void p1() 
  { 
    try { 
      n1(); 
    } 
    catch (Exception e) 
    { 
      System.out.println("Exception handled"); 
    } 
  } 
  public static void main(String args[]) 
  { 
    Demo obj = new Demo(); 
    obj.p1(); 
  } 
}