在Java SE 8中使用“精确重新抛出最终异常”吗?

时间:2015-06-10 17:21:52

标签: java exception

Initialize-AWSDefaults

$cwNamespace = 'Historical CW Sanity Check'
# generate some data 
$now = [DateTime]::Now.ToUniversalTime()

$startTime = $now - [TimeSpan]::FromDays(14)

$t = $startTime
$x = 0

while ($t -le $now)
{

    $t += [TimeSpan]::FromHours(1)

    $datum = New-Object -TypeName 'Amazon.CloudWatch.Model.MetricDatum'

    $datum.Unit = [Amazon.CloudWatch.StandardUnit]::Count
    $datum.Value = 2 * $x
    $datum.Timestamp = $t
    $datum.MetricName = 'Test 2'

    $x +=1.0
    Write-Host "($t, $x)"
    Write-CWMetricData -Namespace $cwNamespace -MetricData $datum

}

大家好,

我的JDK版本是8u45,现在是最新版本。

我想知道在SE 8中仍在使用“精确重新抛出最终例外”吗?

作为代码,如果我将“抛出异常”关闭,那将是编译错误,但是应该能够根据SE7的“精确重新抛出最终异常”函数来忽略它。

另一个问题是我们都知道嵌套的try框中是否发生异常,我们仍然应该将它抛出到外部catch框以避免编译错误,我原本认为我们只需要抛出任何类型的异常&安培;它会这样做,我的测试结果也是如此,我认为让编译器知道try box&中有一个例外。抓箱子也得到了它。

但如果我改变它,就像下面的代码一样:

public class TestException extends except2 {

    public static void main(String[] args)throws Exception  {
       try {
            try {
                throw new TestException();
            }
            catch (final TestException e){         
            }
            throw new except2();
        }
        catch (TestException a){
        }
        catch (Exception e){
            throw e;
        }
    }

    public TestException(){
    }
}

class except2 extends Exception{
}

public class TestException extends except2 { public static void main(String[] args)throws Exception { try { try { throw new ArithmeticException(); } catch (final TestException e){ throw e; } } catch (TestException a){ } catch (Exception e){ throw e; } } } 部分将出现编译错误消息:

“异常”com.xxx.TestException“永远不会在相应的try块中抛出”,

我感到困惑,因为如果嵌套的catch块无法处理异常,它将转到外部。

然后,如果我在外部try块的末尾抛出一个(final TestException e),如下所示:

ArithmeticException

外部捕捉框try { try { throw new TestException(); } catch (final TestException e){ System.out.println("d"); } throw new ArithmeticException(); } catch (TestException a){ } catch (Exception e){ throw e; }

的错误相同

为什么?

它应该被catch (TestException a){}阻止。

如果我不能从嵌套try块的第一个异常中抛出不同类型的异常,为什么我可以在代码的第一段中抛出except2?

2 个答案:

答案 0 :(得分:2)

这是该功能的Oracles示例,它仍适用于Java 8:

static class FirstException extends Exception { }
static class SecondException extends Exception { }

public void rethrowException(String exceptionName)
   throws FirstExceptio, SecondException // Since J7 no "Exception" needed
{
  try {
    if (exceptionName.equals("First")) {
      throw new FirstException();
    } else {
      throw new SecondException();
    }
  } catch (Exception e) {
    throw e; // effective final (i.e. not assigned)
  }
}

这在Oracle document的后半部分进行了描述。你的例子都与它无关。尤其不是那种你更具特色和一般性的捕获物。这在文档中明确提到不起作用。

如果您使用except2(我将其重命名为BaseException),那么您的第一个块就可以使用了,这是更具体的一个:

public class TestException extends BaseException {

    public static void main(String[] args) {
       try {
            try {
                throw new TestException();
            }
            catch (final BaseException e){
              throw e; // this is defined as BaseEx, will fail on Java 6
            }
        }
        catch (TestException a){ // this knows that no BaseEx is expected
        }
    }

    public TestException(){
    }
}

class BaseException extends Exception { }

如您所见,main()方法不再需要抛出Exception,因为第二个catch块已经足够了。

答案 1 :(得分:1)

您的第一段代码可以缩短为

class TestException extends except2 throws Exception {
    public static void main(String[] args) {
        try {
            throw new except2(); // this
        } catch (TestException a) {
        } catch (Exception e) {
            throw e;
        }
    }

    public TestException() {
    }
}

class except2 extends Exception {
}

你正在抛出一个except2TestExceptionexcept2,但except2不一定是TestException。第一个catch块无法处理except2异常。所以第二个必须。由于它进一步throws该异常,并且必须检查该异常,因此您需要有throws子句。

你的第二段代码

class TestException extends except2 {
    public static void main(String[] args) throws Exception {
        try {
            try {
                throw new ArithmeticException();
            } catch (final TestException e) { // nothing above throws a TestException
                throw e;
            }
        } catch (TestException a) {
        }
        catch (Exception e) {

            throw e;
        }
    }
}

尝试在嵌套的TestException块中捕获try。但由于TestException是一个经过检查的异常,编译器可以并且确实检查它是否可以在该块中抛出。在你的情况下,它不能。所以它抱怨尝试抓住它是没用的。

最后,在你的最后一个片段中

class TestException extends except2 {
    public static void main(String[] args) throws Exception {
        try {
            try {
                throw new TestException();
            } catch (final TestException e) {
                System.out.println("d");
            }
            throw new ArithmeticException();
        } catch (TestException a) {
        } catch (Exception e) {
            throw e;
        }
    }
}

您在嵌套的TestException语句中抛出并捕获try-catch。所以你可以将代码减少到

class TestException extends except2 {
    public static void main(String[] args) throws Exception {
        try {
            throw new ArithmeticException();
        } catch (TestException a) {
        } catch (Exception e) {
            throw e;
        }
    }
}

与第二段代码存在相同的问题。那里没有可以抛出TestException的代码路径。

关于注释,并简化第二个片段,错误会缩减为

class TestException extends except2 {
    public static void main(String[] args) throws Exception {
        try {
            throw new ArithmeticException();
        } catch (final TestException e) { // nothing above throws a TestException
            throw e;
        }
    }
}

你有一个catch(TestException)但没有抛出一个TestException,所以这是编译器拒绝的无用代码。

从评论中,这是您的案例2和3的问题

// ignore everything around this
try {
    // nothing in this block 
    // can throw a TestException

    throw new ArithmeticException();

// this whole catch block is useless code
// Test Exception can never be thrown
} catch (final TestException e){ 
    throw e;
} 
// ignore everything around this