否则,Kotlin检查两次null

我有一个variablesdatePurchased的项目,可以为null。 根据购买日期,我生成一个标签。 当我检查datePurchased是否为空,否则我仍然必须检查为空。 它说聪明的演员是不可能的,因为这是一个可变的财产。

以下是我迄今为止所尝试的:

 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 -> { } } 

感谢marstran,我结束了这样的解决方案:

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

如果你确信你没有数据竞争,那么在哪个datePurchased变为null ,然后在else分支中添加一个非null断言:

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

或者更短,更可靠:

 datePurchased?.isToday() ?: "" 
  1. datePurchased是可变的,这意味着它可以改变。

  2. 您的代码不在任何types的同步锁中运行,这意味着另一个线程可能会同时运行并修改它。

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

 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()) { ... } } 

但主要的是,你现在需要考虑在你的应用程序的上下文中不可变的真正含义,以及你是否真的需要variables可变。