Котлин дважды проверяет нуль, если еще

У меня есть элемент с переменной datePurchased , который может быть нулевым. Основываясь на дате покупки, я создаю ярлык. Когда я проверяю, имеет ли datePurchased значение null, в ветке else мне все равно нужно проверить значение null. В нем говорится, что умный литье невозможно, потому что это свойство mutable.

Вот что я пробовал до сих пор:

 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 :

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

    Или короче и надежнее:

     datePurchased?.isToday() ?: "" 
    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()) { ... } } 

    Но главное – теперь вам нужно подумать о том, что неизменяемо на самом деле означает в контексте вашего приложения, и действительно ли вам нужно изменить переменные.