当前位置: 首页 > 知识库问答 >
问题:

“带有最终异常的精确重演”在JavaSE8中有效吗?

方谦
2023-03-14
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{
}

嗨大家好,

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

我想知道“最后一个例外的精确重演”在SE 8中仍然有效吗?

作为代码,如果我去掉“抛出异常”,这将是编译错误,但根据SE7的“最终异常精确重试”函数,应该可以忽略它。

另一个问题是,我们都知道如果嵌套的try框中发生了异常,我们仍然应该将其抛出到外部捕获框以避免编译错误,我最初认为我们只需要抛出任何类型的异常

但是如果我像下面的代码那样修改它:

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;
        }
    }
}

(最终测试例外e)部分将出现编译错误,并显示以下消息

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

我很困惑,因为如果嵌套的捕获块不能处理异常,它将转到外部。

然后,如果我在外部try块的末尾抛出一个算术异常,如下所示:

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){}

那是为什么呢?

它应该被(异常e)块捕获。

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

共有2个答案

关昊天
2023-03-14

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

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 {
}

你抛出一个except2。一个TestExc0019是一个except2,但是一个except2不一定是一个TestExc0019。第一个cat块不能处理except2异常。所以第二个必须。因为它进一步抛出了该异常,并且该异常必须被检查,所以您需要有一个抛出子句。

你的第二段代码

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;
        }
    }
}

正在尝试捕获嵌套的try块中的TestException。但是由于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;
        }
    }
}

您正在嵌套的try catch语句中抛出并捕获一个TestException。因此,您可以将代码简化为

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

这与您的第二段代码有相同的问题。那里没有可以抛出TestExc0019的代码路径。

关于注释,为了简化第二个代码段,错误减少到

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
闾丘康安
2023-03-14

这是该功能的Oracle示例,它仍然适用于Java8:

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文档的后半部分对此进行了描述。你的例子都与此无关。尤其不是你有一个更具体和一般的捕获。文件中明确提到这是不起作用的。

如果您使用except2(我将其重命名为BaseExc0019),则第一个块将起作用,这是更具体的一个:

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()方法不再需要抛出异常,因为第二个catch块已经足够了。

 类似资料:
  • 在Java8中,Java设计者提出了一个有效的final变量的概念,即一个如果被“final”追加就不会给编译器带来错误的变量。我的问题是,这个新提出的“有效最终”概念比经典的“最终”提供了什么?作为一名Java开发人员,我实际上得到了什么好处?

  • 我正在使用RxVertx,它是一种RxJava和Java8,我有一个编译错误。 这是我的代码: 编译错误是:“在封闭范围内定义的局部变量游戏必须是最终的或有效的最终的” 我无法将“game”定义为final,因为我在函数末尾执行分配\set并返回它。 如何编译此代码? 谢了。

  • 有效的最终代码 有更详细的区别吗?

  • 到目前为止,我认为有效的final和final或多或少是等价的,如果在实际行为中不完全相同,JLS会将它们视为相似的。然后我发现了这个人为的场景: 显然,JLS在这两者之间产生了重要的区别,我不知道为什么。 我阅读其他线程,如 最终和有效最终之间的差异 有效的最终变量vs最终变量 变量“有效最终”是什么意思 但他们并没有详细说明。毕竟,在更广泛的层面上,它们似乎几乎相当。但深入研究,他们显然有所不

  • 为什么下面的代码会引发如下所示的异常? 例外情况:

  • 问题内容: 对于我在ANTLR中的语法,我的Java代码可以捕获并打印包含“ $”的输入的错误。在我的实现中,我需要打印出“成功”以便成功输入。因此,我在Java代码中进行了跟踪, 对于我的情况,对于错误的输入,getNumberofSyntaxErrors返回大于0的数字。对于“ int i;”,输出为公正; 当我为int $ i;之类的输入运行代码时,由于getNumberofSyntaxEr