重构之以异常代码取代错误码
1.以异常代码取代错误码
在开发中经常会遇到一个方法返回一个特定的代码来表示某种错误的情况,这种可以改用抛出异常代替错误码。
void withdraw(int amount) {
if (balance < amount) {
return -1;
} else {
balance -= amount;
return -1;
}
}
改为:
void withdraw(int amount) {
if (amount > balance) {
throw new IllegalArgumentException("amount too large");
}
balance -= amount;
}
2.异常分为可控异常和不可控异常:
-
可控异常(checked exception)
继承自java.lang.Exception的异常,这种异常需要显式的try/catch或throw出来,否则编译不通过;
-
不可控异常(unchecked exception)
继承自java.lang.RunTimeException的异常,这种异常不需要显式的try/catch或throw出来编译就能通过。
之所以使用这种异常,是因为这种异常可以简化代码。然而,由于不需要额外处理就能编译通过,所以最好在调用前检查一下可能发生的错误,比如空指针、数组越界等。
3.使用受控异常
使用非受控异常就表示调用者应负责检查参数等是否正确。也就是说,应该在调用业务逻辑方法前先检查各项条件是否正常,而不是直接调用业务逻辑方法,靠其返回值等方式来判断是否执行成功。
比如取钱的业务逻辑,使用withdraw
方法来更新账户。
不合适的代码:
if (withdraw(amount) == -1) {
handleOverdrawn();
} else {
doTheUsualThing();
}
应替换为:
if (!account.canWithdraw(amount)){
handleOverdrawn();
} else {
account.withdraw(amount);
doTheUsualThing();
}
同时,可以使用断言来清楚地指出withdraw
方法中的错误,修改withdraw
方法:
class Account {
void withdraw(int amount) {
Assert.isTrue("sufficient funds", amount <= balance);
balance -= amount;
}
}
class Assert {
static void isTrue(boolean test, String comment) {
if (!test) {
throw new RunTimeException("Assertion fail: " + comment);
}
}
}
4.使用不可控异常
使用不可控异常,可以自定义一个异常,也可以使用现有的异常:
class BalanceException extends Exception {}
在调用withdraw
方法时使用try/catch
:
try {
account.withdraw(amount);
doTheUsualThing();
} catch (BalanceException) {
handleOverdrawn();
}
withdraw
方法修改为:
void withdraw(int amount) throws BalanceException {
if (amount > balance) {
throw new BalanceException();
}
balance -= amount;
}