multi-catch 块中异常问题的引用类型
reference type of exception issue in multi-catch block
e 是 Exception 类型,但在下面的代码中打印 Exception1:
class Exception1 extends IOException {void info(){}}
class Exception2 extends Exception {}
class TestMultiCatch {
public static void main(String args[]) {
try {
int a = 10;
if (a <= 10)
throw new Exception1();
else
throw new Exception2();
} catch (Exception1 | Exception2 e) {
e.info(); //line 1 error "The method info() is undefined for type Exception"
System.out.println(e); //prints Exception1 (after commenting line 1)
}
}
}
根据我的研究 "e" 应该是 Exception 类型,它是 Exception1 和 Exception2 的公共基础 class。确实如此,从第 1 行的消息可以看出。
但是为什么:
System.out.println(e); //prints Exception1 and not Exception
System.out.println(e instanceof IOException); //prints true and not false
System.out.println(e instanceof Exception1); //prints true and not false
System.out.println(e instanceof Exception2); //false
?
谢谢
当您使用 multi-catch 子句(catch
的 Exception1 | Exception2 e
形式)时,e
的编译时类型是这两种类型共有的最大类型,因为当然代码必须处理任何一种类型 exception.From the spec:
An exception parameter may denote its type as either a single class type or a union of two or more class types (called alternatives). The alternatives of a union are syntactically separated by |
.
A catch clause whose exception parameter is denoted as a single class type is called a uni-catch clause.
A catch clause whose exception parameter is denoted as a union of types is called a multi-catch clause.
...
The declared type of an exception parameter that denotes its type as a union with alternatives D1 | D2 | ... | Dn
is lub(D1, D2, ..., Dn)
.
...其中 lub
是定义的最小上限 here.
如果您想使用任何特定于 Exception1
或 Exception2
的内容,请使用单独的 catch
块:
} catch (Exception1 e) {
// Something using features of Exception1
} catch (Exception2 e) {
// Something using features of Exception2
}
如果 info
存在于 Exception1
和 Exception2
上,重构它们以便 info
存在于它们的共同祖先 class 上:
class TheAncestorException extends Exception {
public void info() { // Or possibly make it abstract
// ...
}
}
class Exception1 extends TheAncestorException {
// Optionally override `info` here
}
class Exception2 extends TheAncestorException {
// Optionally override `info` here
}
...所以编译器可以给 e
类型 TheAncestorException
并使 info
可访问。
catch (Exception1 | Exception2 e) {....}
这里e
是Exception1和Exception2的引用变量。所以在编译时 e.info();
将抛出异常,因为 info()
不存在 Exception2
.
最好为每个使用单独的 catch 块,因为两者 类 没有相同的方法 info()
。
} catch (Exception1 e) {
e.info();
System.out.println(e);
} catch (Exception2 e) {
System.out.println(e);
}
multi-catch 似乎是你的问题。您(编译器)只能访问在共同祖先上定义的方法。当然,"e" 在运行时将是 Exception1,但编译器不能假定它,因为它也可能是 Exception2。最好为 Exception1 和 Exception2 创建一个 catch 块。
e 是 Exception 类型,但在下面的代码中打印 Exception1:
class Exception1 extends IOException {void info(){}}
class Exception2 extends Exception {}
class TestMultiCatch {
public static void main(String args[]) {
try {
int a = 10;
if (a <= 10)
throw new Exception1();
else
throw new Exception2();
} catch (Exception1 | Exception2 e) {
e.info(); //line 1 error "The method info() is undefined for type Exception"
System.out.println(e); //prints Exception1 (after commenting line 1)
}
}
}
根据我的研究 "e" 应该是 Exception 类型,它是 Exception1 和 Exception2 的公共基础 class。确实如此,从第 1 行的消息可以看出。
但是为什么:
System.out.println(e); //prints Exception1 and not Exception
System.out.println(e instanceof IOException); //prints true and not false
System.out.println(e instanceof Exception1); //prints true and not false
System.out.println(e instanceof Exception2); //false
? 谢谢
当您使用 multi-catch 子句(catch
的 Exception1 | Exception2 e
形式)时,e
的编译时类型是这两种类型共有的最大类型,因为当然代码必须处理任何一种类型 exception.From the spec:
An exception parameter may denote its type as either a single class type or a union of two or more class types (called alternatives). The alternatives of a union are syntactically separated by
|
.A catch clause whose exception parameter is denoted as a single class type is called a uni-catch clause.
A catch clause whose exception parameter is denoted as a union of types is called a multi-catch clause.
...
The declared type of an exception parameter that denotes its type as a union with alternatives
D1 | D2 | ... | Dn
islub(D1, D2, ..., Dn)
.
...其中 lub
是定义的最小上限 here.
如果您想使用任何特定于 Exception1
或 Exception2
的内容,请使用单独的 catch
块:
} catch (Exception1 e) {
// Something using features of Exception1
} catch (Exception2 e) {
// Something using features of Exception2
}
如果 info
存在于 Exception1
和 Exception2
上,重构它们以便 info
存在于它们的共同祖先 class 上:
class TheAncestorException extends Exception {
public void info() { // Or possibly make it abstract
// ...
}
}
class Exception1 extends TheAncestorException {
// Optionally override `info` here
}
class Exception2 extends TheAncestorException {
// Optionally override `info` here
}
...所以编译器可以给 e
类型 TheAncestorException
并使 info
可访问。
catch (Exception1 | Exception2 e) {....}
这里e
是Exception1和Exception2的引用变量。所以在编译时 e.info();
将抛出异常,因为 info()
不存在 Exception2
.
最好为每个使用单独的 catch 块,因为两者 类 没有相同的方法 info()
。
} catch (Exception1 e) {
e.info();
System.out.println(e);
} catch (Exception2 e) {
System.out.println(e);
}
multi-catch 似乎是你的问题。您(编译器)只能访问在共同祖先上定义的方法。当然,"e" 在运行时将是 Exception1,但编译器不能假定它,因为它也可能是 Exception2。最好为 Exception1 和 Exception2 创建一个 catch 块。