在编码的时候,我们需要做很多的检测判断,比如某个变量是否为null
,某个成员属性是否为true
,执行某个操作结果是否成功。比如像下面的这段代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | var isDiskMounted = true fun createNewFile(file: File?): Boolean { return if (isDiskMounted) { if (file != null) { file.createNewFile() if (file.exists()) { true } else { println("Create file($file) failed") false } } else { println("File($file) is null") false } } else { println("Disk is not mounted") false } } |
---|
上面的代码实现了
但是上面的代码也有一些问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | fun createNewFileV2(file: File?): Boolean { check(isDiskMounted) { "Disk is not mounted" } requireNotNull(file) { "file is null" } file.createNewFile() assert(file.exists()) { "createNewFileV2 file($file) does not exist" } return true } |
---|
file.createNewFile()
执行时可以不需要再使用file?.createNewFile()
这一点是因为使用了Contract。require(boolean)
用来检测方法的参数,当参数boolean为false时,抛出IllegalArgumentException
1 2 3 4 5 6 7 8 9 10 11 12 | fun readFileContent(file: File?): String { //判断file不能为null requireNotNull(file) //判断文件必须可读,并提供错误的信息 require(file.canRead()) { "readFileContent file($file) is not readable" } //read file content return "Your file content" } |
---|
fun require(value: Boolean)
fun require(value: Boolean, lazyMessage: () -> Any)
fun <T : Any> requireNotNull(value: T?)
fun <T : Any> requireNotNull(value: T?, lazyMessage: () -> Any)
check(boolean)
用来检测对象的状态(属性),如果boolean为false,抛出异常IllegalStateException
1 2 3 4 5 6 7 8 9 10 11 12 13 | class Engine { var isStarted = false fun speedUp() { check(isStarted) { "Engine is not started, cannot be speed up now" } //speed up the engine } } |
---|
fun check(value: Boolean, lazyMessage: () -> Any)
fun <T : Any> checkNotNull(value: T?)
fun <T : Any> checkNotNull(value: T?, lazyMessage: () -> Any)
assert(boolean)
用来检测执行结果,当boolean为false时,抛出AssertionError
。但是需要在开启对应的JVM选项时才生效。1 2 3 4 5 6 7 8 | fun makeFile(path: String) { val file = File(path) file.createNewFile() assert(file.exists()) { "make File($file) failed" } } |
---|
check
检测对象的状态require
检测方法的参数合法性assert
校验结果()-> Any
,结合inline操作,可以实现惰性求值require
,check
,assert
都会在发现错误的时候抛出异常1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | fun main() { createNewFile(null) safeRun { createNewFileV2(null) } } private val isDebug = true fun safeRun(block: () -> Unit) { try { block() } catch (t: Throwable) { t.printStackTrace() if (isDebug) { throw t } } } |
---|