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

在下面的代码片段中了解异常处理

邵亦
2023-03-14

考虑下面的代码片段

在代码片段1中,方法m1()在抛出声明中有SQLExctive,但它实际上抛出了类型为Exctive的引用变量。我在这里期待编译器出错,因为抛出声明中没有提到Exctive。但是它编译并打印成功捕获

import java.sql.SQLException;
public class Snippet1{
    private static void m() throws SQLException{
        try{
            throw new SQLException();
        } catch(Exception e){
            throw e;
        }
    }

    public static void main(String[] args){
        try{
            m();
        } catch(SQLException e){
            System.out.println("Caught successfully"); //prints "Caught successfully
        }
    }
}

代码片段2与前一个几乎相同,只是我们将null赋给异常引用变量e,然后将其抛出。现在编译器抱怨必须捕获Exctive或声明才能抛出。

import java.sql.SQLException;
public class Snippet2{
    private static void m() throws SQLException{
        try{
            throw new SQLException();
        } catch(Exception e){
            e = null;
            throw e;
        }
    }

    public static void main(String[] args){
        try{
            m();
        } catch(SQLException e){
            System.out.println("Caught successfully");
        }
    }
}

共有2个答案

葛阳
2023-03-14

JLS中有一个相当特殊的巫毒魔法规则,在JDK6之后的某个时候引入(我认为在JDK7中,与“多捕获”一起,您可以命名多个异常类型,用条形码(|)字符分隔)。

如果捕捉到“过于宽泛”的异常类型,并且变量是final或“有效final”(从未重新分配),那么任何都会抛出t 语句,其中t表示该变量被视为仅代表关联的try主体实际可能抛出的异常类型。

换句话说:

  • 在第一个片段中,您的异常e实际上是最终的,因此规则会启动。
  • 如果规则开始执行,那么在代码段1中,抛出e;就会被视为e实际上被收紧为try body可以抛出的所有类型的不相交类型,这些类型被键入为Exctive或其某些子类型。在这种情况下,这意味着:只是SQLExctive。方法主体被声明为抛出SQLExctive,因此,抛出e;是可以接受的。
  • 在第二个片段中,e不再是有效的最终值,因为它被重新分配了。因此,这个规则不启动,并且抛出e;被简单地解释为试图抛出异常,这是不合法的,因为方法主体不抛出它,并且抛出语句不在try块中,其get块处理异常

添加此功能的目的是让编写想要“窥视”抛出异常的代码变得更简单——他们希望在异常发生时做一些事情,但之后他们希望异常处理继续进行,就像他们没有做一样,也就是说,异常仍然被抛出,完全不变。这或多或少就是finally的作用,除了finally在所有情况下都会运行:所有异常类型,即使try主体正常完成或控件流出,也会运行。

正式留档的相关部分是Java语言规范§11.2.2。

段干弘扬
2023-03-14

这在具有更包容类型检查的JDK 7重抛异常中有所描述

public void rethrowException(String exceptionName)
 throws FirstException, SecondException {
   try {
     // ...
   }
   catch (Exception e) {
     throw e;
   }
 }

JavaSE 7编译器可以确定语句抛出e抛出的异常必须来自try块,try块抛出的唯一异常可以是FirstExctive秒异常。即使get子句的异常参数e是类型Exctive,编译器也可以确定它是FirstExctive秒异常的实例

如果在捕捉块中将捕捉参数分配给另一个值,则禁用此分析。但是,如果将捕捉参数分配给另一个值,则必须在方法声明的throws子句中指定异常类型Exctive

 类似资料:
  • 本文向大家介绍带你了解Java中的异常处理(下),包括了带你了解Java中的异常处理(下)的使用技巧和注意事项,需要的朋友参考一下   今天继续讲解java中的异常处理机制,主要介绍Exception家族的主要成员,自定义异常,以及异常处理的正确姿势。 Exception家族   一图胜千言,先来看一张图。   Exception这是一个父类,它有两个儿子,IOException和RuntimeE

  • 了解如何使用 Dreamweaver的“代码片段”面板创建代码片段并在不同的 Dreamweaver 站点上重用代码。 如果您发现自己多次重复代码块,可以使用代码片段加快编写代码的过程。写入该代码一次,将其保存为一个代码片段,然后在“代码片段”面板中双击它,以将它插入到多个位置。 使用“代码片段”面板创建的代码片段不是针对特定站点的,因此可以跨站点重用它们。您还可以使用同步设置跨不同设备、Drea

  • 我的类有一个名为的私有对象,其构造函数需要另一个类的实例。 如果失败,如何引发异常?

  • 我在做关于Leetcode上大多数水问题的容器 问题: 给定n个非负整数a1,a2。。。,an,其中每个代表坐标(i,ai)处的一个点。绘制n条垂直线,使线i的两个endpoint位于(i,ai)和(i,0)。找到两条线,这两条线与x轴一起构成一个容器,使容器包含最多的水。 注意:容器不能倾斜,n至少为2。 问题链接:https://leetcode.com/problems/container-

  • 本文向大家介绍了解C++编程中指定的异常和未经处理的异常,包括了了解C++编程中指定的异常和未经处理的异常的使用技巧和注意事项,需要的朋友参考一下 noexcept C++11:指定函数是否可能会引发异常。 语法 参数 表达式 计算结果是 True 或 False 的常量表达式。无条件版本相当于 noexcept(true)。 备注 noexcept(及其同义词 noecept(true))指定函

  • 此代码来自C primer p.446: 我不明白带两对括号的返回表达式。这本书前面没有类似的语法。