我有以下代码
public enum Animal {
DOG,CAT;
private void exitWithError(String message){
System.out.println(message);
System.exit(1);
}
@Override
public String toString() {
switch(this){
case DOG:
return "dog";
case CAT:
return "cat";
default:
// missing return statement error
exitWithError("unrecognized animal");
/*
workaround - don't like it
return null;
*/
/* no error if exception thrown
throw new IllegalStateException("unrecognized animal");
*/
}
}
}
上面的代码导致missing return statement
错误。我有一些问题:
exitWithError
方法应该总是完成程序的执行,对吗?如果方法总是退出,是否有任何方法我可以通知编译器关于它,所以它不会把
missing return statement
扔给我?
return null
解决方案似乎是糟糕的代码,如果代码改变了,这个返回语句将被执行,它可能会导致问题。
toString()
方法不应该退出程序。更一般地说,几乎没有方法应该试图退出程序。
想想System.out.println(EnumSet.allOf(Animal.class));
导致程序退出是多么令人惊讶。(它不会,现在,但它可能会如果你添加另一个动物,忘记更新toString()
)。
如果你想在这里指出错误,抛出一个异常(或错误),允许调用者处理它,如果他们能够:
@Override
public String toString() {
switch(this){
case DOG:
return "dog";
case CAT:
return "cat";
}
throw new AssertionError();
}
throw
实际上是不可访问的,但编译器不知道这一点:throw
是必要的,以使编译器相信该方法不能正常完成(即不返回值或抛出)。
或者,在Java 12+中,编译器将检查枚举上的switch表达式的完整性:
return switch (this) {
DOG -> "dog";
CAT -> "cat";
})
然而,另一种方法(在java 12之前可用)是将toString()
作为构造函数的参数,这样您就不必担心没有已知toString()
的Animal
:
enum Animal {
DOG("dog"), CAT("cat");
private String string;
Animal(String string) { this.string = string; }
@Override public String toString() { return string; }
}