用于处理非空对象和非空字符串表示的Kotlin习语

时间:2017-05-23 15:32:04

标签: conditional-statements kotlin tostring nullable

我有一个可以为null的属性(一个Java对象)知道如何将自己转换为String,如果这个表示不为空,我想用它做一些事情。在Java中,这看起来像:

MyObject obj = ...
if (obj != null) {
    String representation = obj.toString();
    if (!StringUtils.isBlank(representation)) {
        doSomethingWith(representation);
    }
}

我试图找到将此转换为Kotlin的最惯用的方式,我有:

    with(obj?.toString()) {
        if (!isNullOrBlank()) {
            doSomethingWith(representation)
        }
    }

但对于这么简单的操作来说,它仍然感觉太多了。我有这样的感觉,即letwhenwith合并后,我可以将其缩小到更短的时间。

步骤如下:

  1. 如果对象(A)不为空
  2. 如果对象(A)的字符串表示(B)不是空白
  3. 用(B)
  4. 做点什么

    我试过了:

        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,我并不是真正关心的。{/ p>

    " Kotlin方式"这里吗

1 个答案:

答案 0 :(得分:13)

您可以使用(自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安全访问器,有时则不使用。{1}} null安全访问器。这是因为某些函数的predicat / lambdas使用可空值,而其他函数则没有。您可以按照自己的方式设计这些。这取决于你!

有关此主题的更多信息,请参阅:Idiomatic way to deal with nullables