Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/394.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 确定编译时多批次异常类型_Java_Exception_Try Catch_Java 7_Multi Catch - Fatal编程技术网

Java 确定编译时多批次异常类型

Java 确定编译时多批次异常类型,java,exception,try-catch,java-7,multi-catch,Java,Exception,Try Catch,Java 7,Multi Catch,我建造了一些我并不真正理解的东西——我不知道它是如何工作的。我已经熟悉了这一点 考虑以下两种例外情况和代码: public class MyException1 extends Exception { // constructors, etc String getCustomValue(); } public class MyException2 extends Exception { // constructors, etc String getCustomValue() {

我建造了一些我并不真正理解的东西——我不知道它是如何工作的。我已经熟悉了这一点

考虑以下两种例外情况和代码:

public class MyException1 extends Exception {
  // constructors, etc
  String getCustomValue();
}

public class MyException2 extends Exception {
  // constructors, etc
  String getCustomValue() { return "foo"; }
}

try {
  //...
} catch (MyException1|MyException2 e) {
  e.getCustomValue(); // won't work, as I expected
}
即使方法相同,我也无法调用
getCustomValue()
,因为在Java内部,上面的
try/catch
实际上是将
MyException1/2
转换为
异常
(这就是我对文档的理解)

但是,如果我引入这样的接口:

public interface CustomValueGetter {
  String getCustomValue();
}

public class MyException1 extends Exception implements CustomValueGetter /*...*/
public class MyException2 extends Exception implements CustomValueGetter /*...*/
将它添加到两个例外中,Java实际上能够允许我使用该方法。然后调用此命令是有效的:

try {
  //...
} catch (MyException1|MyException2 e) {
  e.getCustomValue(); // does work
}
简而言之,我的问题是:这里实际发生了什么:
(MyException1 | myException2e)

什么是
e

  • 是否选择最接近的超类作为
    e
    的类型?据推测,这就是答案。如果是这样,那么为什么当我访问e时CustomValueGetter接口“可见”?在我的例子中,如果
    e
    是一个
    异常
    ,就不应该这样

  • 如果不是,如果真正的类是
    MyException1
    MyException2
    为什么我不能简单地调用这两个类可用的相同方法

  • e
    是否是动态生成的类的实例,该类实现了两个异常的所有公共接口,并且是最接近的公共SuperClass类型


在第一个代码示例中,Java无法自动推断
MyException1
MyException2
都实现了函数
getCustomValue
。因此,
e
是两者类型层次结构中最大的公分母;这是
异常
,没有函数
getCustomValue
。因此,它不起作用

Java是强类型的,尽管函数的名称相似,但它与以相同类型声明的函数并不相同


在第二个代码中,两个异常都实现了
CustomValueGetter
。因此,
e
是最大的公分母
CustomValueGetter
,它实现了
getCustomValue

,,正如Ischuetze所说,e正在寻找两个异常都共享的类或接口。在中的第一个示例中,尽管存在异常类,但无法找到共享类,因此它只能使用它提供的方法

将示例更改为此代码将能够再次编译

public class MyException12 extends Exception {
    public String getCustomValue(){ return "boo"; };
}

public class MyException1 extends MyException12{
    public String getCustomValue() { return "foo"; };
}

public class MyException2 extends MyException12{
    // constructors, etc
    public String getCustomValue() { return "foo"; };
}
与您的界面示例一样,异常通知
MyException1
MyException2
都具有
MyException12
,因此能够使用其功能

这是一个很好的问题,回答了整个问题以及e的类型

答案中的链接引用:

更改异常类型的处理会以两种方式影响类型系统:除了对所有类型执行常规的类型检查之外,异常类型还要进行额外的编译时分析。为了进行类型检查,使用析取声明的catch参数具有类型lub(t1,t2,…)(JLSv3§15.12.2.7),其中ti是声明catch子句要处理的异常类型。非正式地说,lub(最小上界)是所讨论类型中最具体的超类型。在多捕获异常参数的情况下,所讨论的类型的最小上界始终存在,因为所有捕获的异常的类型都必须是Throwable的子类。因此,Throwable是相关类型的上限,但它可能不是最小上限,因为Throwable的某些子类可能是相关类型的超类(因此也是超类型),并且相关异常类型可能实现公共接口。(lub可以是超类和一个或多个接口的交叉类型。)为了进行异常检查(JLSv3§11.2),返回最终或有效最终捕获参数的抛出语句(JLSv3§11.2.2)被视为精确抛出以下异常类型:


挖掘@Kevin Eshche的JLS链接,我似乎找到了一个正确的答案

编译时
e
实际上是一个最小上界,它在中定义

文件摘录:

计算交叉点比一开始可能要复杂得多 认识到。假设类型参数被约束为超类型 泛型类型的两个不同调用,例如List和 列表中,原始交集操作可能会生成对象。 然而,更复杂的分析会产生一组包含 列表类似地,如果类型参数T被约束为 两个不相关的接口I和J的超类型,我们可以推断T必须 要客观,否则我们可能会得到一个更严格的I&J界限。这些问题 本节后面将更详细地讨论


简言之,它是所有
|
'd异常(在我的例子中是
异常
)中最接近的公共超类型的
,并且它实现了所有异常所做的所有接口(在我的例子中是
CustomValueGetter
Serializable
)。

如果你的答案中发布的链接的答案是正确的,那么我使用的接口永远不应该在
e
中解析,因为这两个异常的超类都没有实现它。@Dariusz I edid并在另一个问题的答案中引用了链接,通知后面的部分说:
lub可以是超类和一个或多个接口的交集类型。
太糟糕了,这一措辞没有纳入实际的Java语言文档(编写得非常模糊)。我想最接近的是对的描述,其中提到了“类型推断(§15.12.2.7)”,对的描述也是如此。