对比以下代码:
fun nested() {
if (condition1) {
()
doThings1if (condition2) {
()
doThings2if (condition3) {
()
doThings3} else {
throw Exception3()
}
} else {
throw Exception2()
}
} else {
throw Exception1()
}
}
fun preconditions() {
(condition1)
require(condition2)
require(condition3)
require()
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> {
(count >= 0) { "Count must be non-negative, was $count" }
require// ...
return List(count) { it + 1 }
}
<IllegalArgumentException> { getIndices(-1) }
assertFailsWith
(getIndices(3), "[1, 2, 3]")
assertPrints}
@Sample
fun failCheckWithLazyMessage() {
var someState: String? = null
fun getStateValue(): String {
val state = checkNotNull(someState) { "State must be set beforehand" }
(state.isNotEmpty()) { "State must be non-empty" }
check// ...
return state
}
<IllegalStateException> { getStateValue() }
assertFailsWith
= ""
someState <IllegalStateException> { getStateValue() }
assertFailsWith
= "non-empty-state"
someState (getStateValue(), "non-empty-state")
assertPrints}
同时 error
函数也很有用,他是
throw IllegalStateException
的缩写。
fun failWithError() {
val name: String? = null
<IllegalStateException> { val nonNullName = name ?: error("Name is missing") }
assertFailsWith}
上面的示例来自 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
.createNewFile()
file}
@Test
fun lambdaFastReturn() {
(0, 1, 2, 3, 5, -1).forEach {
listOfif (it < 0) return@forEach
(it >= 0)
assert}
}