如果没有,Kotlin会检查两次null

时间:2016-11-17 10:13:17

标签: kotlin nullable mutable kotlin-null-safety

我有一个变量为datePurchased的项,可以为null。根据购买日期,我生成一个标签。当我检查datePurchased是否为null时,在else分支中我仍然需要检查null。它说智能演员是不可能的,因为它是一个可变的属性。

这是我迄今为止所做的尝试:

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

        }
    }

3 个答案:

答案 0 :(得分:4)

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

{
    "Ghost in the Shell": 
    "id": 6144,
    "name": "Pipeline",
    "status": "New",
    "item_id": 5962,
     "TotalTasksOpen": 2
}

答案 1 :(得分:0)

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

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

或者更短更可靠:

datePurchased?.isToday() ?: ""

答案 2 :(得分:0)

  1. datePurchased是可变的,这意味着它可以被更改。

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

  3. 考虑到这一点,可以采取以下措施:

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

    但主要的是你现在需要考虑不可变在你的应用程序环境中的真正意义,以及你是否真的需要变量是可变的。