【问题标题】:Kotlin check for null twice in if elseKotlin 在 if else 中检查 null 两次
【发布时间】:2017-08-15 05:53:13
【问题描述】:

我有一个变量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                     -> {

        }
    }

【问题讨论】:

标签: kotlin nullable mutable kotlin-null-safety


【解决方案1】:

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

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

            }
        } ?: ""

【讨论】:

    【解决方案2】:

    如果您确信没有 datePurchased 变为 null 的数据竞争,则在 else 分支中添加非空断言:

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

    或者更短更可靠:

    datePurchased?.isToday() ?: ""
    

    【讨论】:

      【解决方案3】:
      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()) { 
              ...
          }
      }
      

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-07-12
        • 1970-01-01
        • 1970-01-01
        • 2023-04-02
        相关资源
        最近更新 更多