我无法抛出特定的异常

时间:2018-06-12 07:27:51

标签: java

@Override
Public class example {
void test {
try {
  someMethod(); //This throws TimeoutException
} catch (TimeoutException ex) {
  throw new TimeoutException(ex); //It doesn't throw error if I replace this with throw new RuntimeException(ex)
} }
}

上面的例子给出了一个错误'throw new TimeoutException(ex)',因为java.util.concurrent.TimeoutException中的“TimeoutException(java.lang.string)”不能应用于(java.util.concurrent.TimeoutException)“

但如果我用'throw new RuntimeException(ex)'替换它,它不会抛出错误;

4 个答案:

答案 0 :(得分:1)

TimeoutException没有一个构造函数接受TimeoutException作为TimeoutException(TimeoutException cause)或类似形式的参数。

您可以改为:

TimeoutException localtoe=new TimeoutException("test failed");
localtoe.initCause(ex);
throw localtoe;

或同样地:

throw new TimeoutException("test failed").initCause(ex);

initCause()只能调用一次,并且只有在构造函数未设置cause时才会调用。这是一个有趣的小方法,就像构思后的思想(*)。

将异常包装为异常原因并没有什么不妥。 假设testFunction()连接然后执行某些操作。 您可能希望抛出一个异常,消息“testFunction中的连接失败”,另一个“testFunction中的操作失败”,具体取决于哪个子步骤失败。

但是如果你不需要提供如此多的细节,你可以throw ex或者让这个方法放松,而不会自己捕捉任何东西。

这是一个小例子:

import java.util.concurrent.TimeoutException;

class Example{

private static void connect() throws TimeoutException {
        //Dummy connection that just fails...   
        throw new TimeoutException("connection failed");
    }

    private static void process() throws TimeoutException {
        try {
            connect();
        }catch(TimeoutException toe){
           TimeoutException toeout=new TimeoutException("process failed because connection failed.");
           toeout.initCause(toe);
           throw toeout;
        }
        //Code for when connection succeeds...
    }

    public static void main (String[] args) throws java.lang.Exception
    {
        try{
            process();  
        }catch(TimeoutException toe){
            System.out.println(toe);
        }
    }
}

预期产出:

java.util.concurrent.TimeoutException: process failed because connection failed.

(*)initCause()看起来像是一个经过深思熟虑的,有点像。它于2002年被添加到Java 1.4中。该文档讨论了“遗留”构造函数。它不是将构造数量增加一倍(添加一个Throwable cause参数),而是决定允许它作为bolt-on初始化。 这是否是最好的解决方案值得商榷。

答案 1 :(得分:0)

这里有三个选项:

  1. 重新抛出同样的例外:`throw ex;'
  2. 抛出新的TimeoutException并丢失堆栈跟踪:throw new TimeoutException(ex.getMessage());
  3. 抛出另一种类型的例外,例如RuntimeException
  4. 您决定,每个选项都有优点和缺点。

    更新(感谢@Mark Rottenveel)

    可以重写第2点:throw new TimeoutException(ex.getMessage()).initCause(ex);以保持指向原始异常的链接。

答案 2 :(得分:0)

我在你的问题中观察到的事情

  1. 您正尝试直接从try缓存块中的类调用方法。你必须创建方法并从那个

  2. 调用它是错误的
  3. 你想抛出异常。所以你必须从你调用它的地方扔掉它的方法级别

  4. 请在下面找到演示解决方案:

    public class example {
    
    public void testFunction() throws TimeoutException {
        try {
            someFunction();
        } catch (TimeoutException ex) {
            throw ex; 
        }
    }
    
    public void someFunction() throws TimeoutException {
    
    }
    }
    

答案 3 :(得分:0)

Java有两类例外:已选中和未选中。必须在函数签名中声明已检查的异常(通常是Exception的子类),而未经检查的异常(通常是RuntimeException的子类)则不能。

TimeoutException是一个经过检查的例外。当它可以从一个没有声明它的方法抛出时,你有两个选择:

  • 在签名中声明:

    public void func1() throws TimeoutException {
        somefunction();
    }
    

    干净简单,但它可能有问题是func1是一个未声明为抛出此异常的函数的覆盖,它是从另一个函数(假设来自框架)调用的,它不会声明它

  • 在未经检查的异常中隐藏

    public void func1() {
        try {
            somefunction();
        } catch (TimeoutException e) {
            throw new RuntimeException(e);
        }
    }
    

    你丢失了声明部分(由于这个原因存在已检查的异常),但至少它允许你从不声明它的函数中调用它。