什么是好的 "unreachable" 开关错误?
What is a good "unreachable" Error for switches?
Eclipse 强制我对任何 switch
使用 default
案例,包括那些列出所有声明的 enum
值的案例,据称是因为语言规范 [1]。这是不幸的,因为并行开发项目的 Android Studio 没有,并且自然会警告我所有 switch
es,如果 enum
被更改,它们将变得不完整。虽然我更喜欢后一种行为,因为前者使 enum
更改实际上 更多 容易出错(请参见下面的示例),但我无法选择,所以我需要找到对两者都正确的方法。我想如果代码中有一个地方在任何情况下都应该保持无法访问,但仍然不能删除该行,那么抛出 Error
似乎是自然而然的事情。但是哪一个,是否有针对这种情况的普遍接受的子类(可能扩展到其他 "forced" 无法到达的地方)?或者只是为了它而简单地抛出一个快速而肮脏的 new Error("enum name")
而不是我自己写一个永远不会被使用的东西是可以接受的吗?
示例中:
public static enum Color {
RED,
GREEN,
BLUE;
@Override
public String toString() {
switch(this) {
case RED:
return "Red";
case GREEN:
return "Green";
case BLUE:
return "Blue";
default:
/* never reached */
throw new ThisCanNeverHappenError();
}
}
}
将 WHITE
添加到 enum
使得这个 switch
并且可能在整个代码中更多的无声源令人讨厌的错误来源,因为流控制发现它们很好。
抛出 Error
s 不是一个非常明智的举动 - 大多数异常处理代码都会通过它们,它们最终会出现在奇怪的地方,可能会使您的进程无法使用。
我会推荐 IllegalStateException
。
Eclipse Bugzilla/Bug 374605 对此进行了长时间的讨论。
最终结果是这是一个可配置的警告,可以禁用。
将下拉列表从警告更改为忽略
如果将 "toString" 值添加为枚举实例的参数,则不需要此开关(以及对默认情况的相应处理):
public static enum Color {
RED("Red"),
GREEN("Green"),
BLUE("Blue");
private final String name;
private Color(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
你不应该抛出 Error
。更好的例外应该是 IllegalStateException
:
switch(this) {
case RED:
return "Red";
case GREEN:
return "Green";
case BLUE:
return "Blue";
default:
throw new IllegalStateException("Unexpected enum value: " + this.name());
}
换句话说,您不应该在那里使用 switch
语句。向枚举中添加一个字段。另请注意,枚举始终是 static
,因此您可以删除该关键字。
public enum Color {
RED ("Red"),
GREEN("Green"),
BLUE ("Blue");
private final String displayText;
private Color(String displayText) {
this.displayText = displayText;
}
public String getDisplayText() {
return this.displayText;
}
@Override
public String toString() {
return this.displayText;
}
}
您正在做出断言:/* never reached */
- 如果该断言是错误的,您可能应该抛出一个 AssertionError
.
抛出 IllegalStateException
的替代建议并不合适 - 根据 javadoc:
Signals that a method has been invoked at an illegal or inappropriate time
实际情况并非如此。
Eclipse 强制我对任何 switch
使用 default
案例,包括那些列出所有声明的 enum
值的案例,据称是因为语言规范 [1]。这是不幸的,因为并行开发项目的 Android Studio 没有,并且自然会警告我所有 switch
es,如果 enum
被更改,它们将变得不完整。虽然我更喜欢后一种行为,因为前者使 enum
更改实际上 更多 容易出错(请参见下面的示例),但我无法选择,所以我需要找到对两者都正确的方法。我想如果代码中有一个地方在任何情况下都应该保持无法访问,但仍然不能删除该行,那么抛出 Error
似乎是自然而然的事情。但是哪一个,是否有针对这种情况的普遍接受的子类(可能扩展到其他 "forced" 无法到达的地方)?或者只是为了它而简单地抛出一个快速而肮脏的 new Error("enum name")
而不是我自己写一个永远不会被使用的东西是可以接受的吗?
示例中:
public static enum Color {
RED,
GREEN,
BLUE;
@Override
public String toString() {
switch(this) {
case RED:
return "Red";
case GREEN:
return "Green";
case BLUE:
return "Blue";
default:
/* never reached */
throw new ThisCanNeverHappenError();
}
}
}
将 WHITE
添加到 enum
使得这个 switch
并且可能在整个代码中更多的无声源令人讨厌的错误来源,因为流控制发现它们很好。
抛出 Error
s 不是一个非常明智的举动 - 大多数异常处理代码都会通过它们,它们最终会出现在奇怪的地方,可能会使您的进程无法使用。
我会推荐 IllegalStateException
。
Eclipse Bugzilla/Bug 374605 对此进行了长时间的讨论。
最终结果是这是一个可配置的警告,可以禁用。
将下拉列表从警告更改为忽略
如果将 "toString" 值添加为枚举实例的参数,则不需要此开关(以及对默认情况的相应处理):
public static enum Color {
RED("Red"),
GREEN("Green"),
BLUE("Blue");
private final String name;
private Color(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
你不应该抛出 Error
。更好的例外应该是 IllegalStateException
:
switch(this) {
case RED:
return "Red";
case GREEN:
return "Green";
case BLUE:
return "Blue";
default:
throw new IllegalStateException("Unexpected enum value: " + this.name());
}
换句话说,您不应该在那里使用 switch
语句。向枚举中添加一个字段。另请注意,枚举始终是 static
,因此您可以删除该关键字。
public enum Color {
RED ("Red"),
GREEN("Green"),
BLUE ("Blue");
private final String displayText;
private Color(String displayText) {
this.displayText = displayText;
}
public String getDisplayText() {
return this.displayText;
}
@Override
public String toString() {
return this.displayText;
}
}
您正在做出断言:/* never reached */
- 如果该断言是错误的,您可能应该抛出一个 AssertionError
.
抛出 IllegalStateException
的替代建议并不合适 - 根据 javadoc:
Signals that a method has been invoked at an illegal or inappropriate time
实际情况并非如此。