用于处理非空对象和非空字符串表示的Kotlin成语
我有一个空的属性(一个Java对象),知道如何将自己转换为一个字符串,如果这种表示不是空的,我想做一些事情。 在Java中,这看起来像:
MyObject obj = ... if (obj != null) { String representation = obj.toString(); if (!StringUtils.isBlank(representation)) { doSomethingWith(representation); } }
我试图找到把这个转换成Kotlin的最习惯的方式,我有:
with(obj?.toString()) { if (!isNullOrBlank()) { doSomethingWith(representation) } }
但是对于这样一个简单的操作,感觉还是太多了。 我有这样一种感觉,即let
我,可以和我在一起when
,可以把它缩短到稍微短一些。
步骤是:
- 如果对象(A)不为空
- 如果对象(A)的字符串表示(B)不是空白的
- (B)
我试过了:
when(where?.toString()) { isNullOrBlank() -> builder.append(this) }
但(1)失败:
Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: @InlineOnly public inline fun CharSequence?.isNullOrBlank(): Boolean defined in kotlin.text @InlineOnly public inline fun CharSequence?.isNullOrBlank(): Boolean defined in kotlin.text
即使它已经过去了,(2)它会希望穷尽else
,我不太在意这一点。
这里有什么“Kotlin的方式”?
您可以使用(自Kotlin 1.1以来)内置的stdlib takeIf()
或takeUnless
扩展,可以工作:
obj?.toString().takeUnless { it.isNullOrBlank() }?.let { doSomethingWith(it) } // or obj?.toString()?.takeIf { it.isNotBlank() }?.let { doSomethingWith(it) } // or use a function reference obj?.toString().takeUnless { it.isNullOrBlank() }?.let(::doSomethingWith)
为了对最终值执行doSomethingWith()
动作,可以使用apply()
在当前对象的上下文中工作,并且返回的是同一个对象,或者let()
改变表达式的结果,或者run()
在当前对象的上下文中工作,还可以改变表达式的结果,或者also()
在返回原始对象时执行代码。
你也可以创建你自己的扩展函数,如果你想命名更有意义,例如nullIfBlank()
可能是一个好名字:
obj?.toString().nullIfBlank()?.also { doSomethingWith(it) }
其定义为可空String
的扩展:
fun String?.nullIfBlank(): String? = if (isNullOrBlank()) null else this
如果我们再添加一个扩展名:
fun <R> String.whenNotNullOrBlank(block: (String)->R): R? = this.nullIfBlank()?.let(block)
这使代码被简化为:
obj?.toString()?.whenNotNullOrBlank { doSomethingWith(it) } // or with a function reference obj?.toString()?.whenNotNullOrBlank(::doSomethingWith)
你总是可以写这样的扩展来提高代码的可读性。
注意:有时我使用了?.
null安全访问者和其他时间不。 这是因为某些函数的预测/ lambda表达式可以使用空值,而其他函数则不能。 你可以设计这些你想要的方式。 随你便!
有关此主题的更多信息,请参阅: 处理空字符的习惯方法