1

我有一个带有变量的项目datePurchased,它可以为空。根据购买日期,我生成一个标签。当我检查 datePurchased 是否为空时,在 else 分支中我仍然必须检查是否为空。它说智能转换是不可能的,因为它是一个可变属性。

这是我到目前为止所尝试的:

if (datePurchased == null) {
    ""
} else {
    if (datePurchased.isToday()) {//error here
    }
}

    when {
        datePurchased == null    -> {

        }
        datePurchased.isToday() -> {//smart cast bla bla mutable bla bla
        datePurchased?.isToday() -> {//expected Boolean, got Boolean?
        datePurchased?.isToday()?:false -> {//all good, but does not look nice, since datePurchased can't be null here
        }
        else                     -> {

        }
    }
4

3 回答 3

4

感谢marstran,我最终得到了这样的解决方案:

        return datePurchased?.let {
            when {
                it.isToday()     -> {
                    "Today"
                }
                it.isYesterday() -> {
                    "Yesterday"
                }
                else             -> {
                    dateFormat.format(it)
                }

            }
        } ?: ""
于 2016-11-18T08:37:42.817 回答
0
  1. datePurchased 是可变的,这意味着它可以更改。

  2. 您的代码没有在任何类型的同步锁中运行,这意味着另一个线程可能正在同时运行和修改它。

考虑到这一点,以下是可能的:

if (datePurchased == null) {
    ...
} else {

    // another thread comes in here and changes datePurchased=null

    if (datePurchased.isToday()) { // Null Pointer Exception!
        ...
    }
}

您可能没有执行此操作的线程,但编译器不知道。它很安全,并说你不能这样做。可能有 98% 的情况是错误的,但另外 2% 的情况会迫使您考虑代码在并发环境中的行为方式。

一种解决方案是简单地使用无法在新线程中更改的本地 val:

val datePurchased = datePurchased

if (datePurchased == null) {
    ...
} else {

    // datePurchased val cannot have been changed, compiler can guarantee safety

    if (datePurchased.isToday()) { 
        ...
    }
}

但最重要的是,您现在需要考虑在您的应用程序上下文中不可变的真正含义,以及您是否真的需要让变量可变。

于 2017-05-09T02:05:54.377 回答
0

如果您确信没有数据竞争,datePurchased那么在分支null中添加一个非空断言:else

if (datePurchased == null) {
    ""
} else {
    datePurchased!!.isToday()
}

或者更短更可靠:

datePurchased?.isToday() ?: ""
于 2016-11-17T18:02:10.503 回答