【发布时间】:2021-08-16 04:34:44
【问题描述】:
我有一个具有以下字段和方法的类:
private final Map<Character, String> charMap = new LinkedHashMap<>();
public Character charOf(String s) {
assert this.charMap.containsValue(s);
for (Character c : this.charMap.keySet()) {
if (this.charMap.get(c).equals(s)) return c;
}
}
编译器不喜欢这样,给我一个“缺少返回语句”错误,而这编译得很好:
private final Map<Character, String> charMap = new LinkedHashMap<>();
public Character charOf(String s) {
for (Character c : this.charMap.keySet()) {
if (this.charMap.get(c).equals(s)) return c;
}
throw new IllegalArgumentException("There is no mapping for \"" + s + "\"");
}
据我所知,这两种方法的功能应该完全相同,并且做的事情完全相同,但前者的可读性略高(但错误消息的详细程度较低)。它总是要么返回一个值,要么抛出一个异常。为什么编译器没有意识到这一点?
【问题讨论】:
-
-
无条件抛出将结束该方法的流程。这种方法再也无法继续下去了。然而,断言是一个可选功能,可以通过 JVM 标志启用和禁用。所以当然可以继续流程,因此会遇到方法结束而不返回的情况,这是不允许的。
-
另外,编译器不够聪明,无法将断言背后的实际逻辑与代码逻辑联系起来。这是静态代码分析器可以做的事情,但编译器不能。
-
附带说明,...使用 Map.Entry 而不是 keySet() + get()。