对比以下代码:
fun nested() {
if (condition1) {
doThings1()
if (condition2) {
doThings2()
if (condition3) {
doThings3()
} else {
throw Exception3()
}
} else {
throw Exception2()
}
} else {
throw Exception1()
}
}fun preconditions() {
require(condition1)
require(condition2)
require(condition3)
doThings1()
doThings2()
doThings3()
}后者的风格显著提高了可读性。
你可以直接使用 Kotlin 标准库中提供的函数。在 Preconditions.kt 中你可以看到一系列先决条件工具方法。
只有一个 value 参数的 require
check,以及具有 lazyMessage 的变体。同样也有
checkNotNull requireNotNull 变体。
require 和 check 的区别不大,在输入的条件为
false 时,前者抛出
IllegalArgumentException,后者抛出
IllegalStateException。
@Sample
fun failRequireWithLazyMessage() {
fun getIndices(count: Int): List<Int> {
require(count >= 0) { "Count must be non-negative, was $count" }
// ...
return List(count) { it + 1 }
}
assertFailsWith<IllegalArgumentException> { getIndices(-1) }
assertPrints(getIndices(3), "[1, 2, 3]")
}
@Sample
fun failCheckWithLazyMessage() {
var someState: String? = null
fun getStateValue(): String {
val state = checkNotNull(someState) { "State must be set beforehand" }
check(state.isNotEmpty()) { "State must be non-empty" }
// ...
return state
}
assertFailsWith<IllegalStateException> { getStateValue() }
someState = ""
assertFailsWith<IllegalStateException> { getStateValue() }
someState = "non-empty-state"
assertPrints(getStateValue(), "non-empty-state")
}同时 error 函数也很有用,他是
throw IllegalStateException 的缩写。
fun failWithError() {
val name: String? = null
assertFailsWith<IllegalStateException> { val nonNullName = name ?: error("Name is missing") }
}上面的示例来自 Kotlin 官方仓库。
如果不想抛出异常:
fun List<Int>.getElement(x: Int): Int? {
if (x !in 0..(size - 1)) return null
return get(x)
}
fun File.touch() {
if (exist()) return
file.createNewFile()
}
@Test
fun lambdaFastReturn() {
listOf(0, 1, 2, 3, 5, -1).forEach {
if (it < 0) return@forEach
assert(it >= 0)
}
}