Что заставляет интерпретировать безопасный вызов (вопросительный знак) иначе, чем классический если?

В Kotlin, если мы объявляем член класса как var и допускающий значение NULL тип, компилятор не позволяет нам запускать функцию-член, хотя мы помещаем оператор if перед вызовом функции, поскольку компилятор не может гарантировать, что члену не присвоено значение null после проверки на значение null и перед вызовом метода. Но если мы используем безопасный вызов, компилятор одобряет наш код. Мой вопрос, как компилятор делает безопасный вызов атомарным? Разве второй поток не может изменять переменную между проверкой нулевого значения и вызовом метода (в примере метод eat)? Код для первой ситуации:

        class MyWolf
{
    var w : Wolf? = Wolf()
    
    fun myFunction()
    {
        if (w != null)
        {
            w.eat()
        }
    }

}

class Wolf
{
    fun eat() : Unit
    println("wolf is eating")
}

Код для второй ситуации:

    class MyWolf
{
    var w : Wolf? = Wolf()
        
    fun myFunction()
    {
        w?.eat()
    }
}

class Wolf
{
      fun eat():Unit
    {
        //code
    }
}

person Eitanos30    schedule 13.10.2020    source источник
comment
Отвечает ли это на ваш вопрос? Является ли Kotlin `? .let` потокобезопасным?   -  person Jonny Henly    schedule 13.10.2020
comment
Поскольку я не понимаю ответа, я не могу сказать :(   -  person Eitanos30    schedule 13.10.2020


Ответы (1)


Компилятор помещает содержимое поля в локальную переменную, а затем сравнивает его с нулевым значением. Вы можете ясно увидеть это, если декомпилируете байт-код Kotlin.

person Konstantin Raspopov    schedule 13.10.2020
comment
Ok. приятно знать. к сожалению, я не умею читать байт-код - person Eitanos30; 13.10.2020
comment
@ Eitanos30 создает несколько вложенных if. В каждом if он вычисляет следующее значение, помещает его в локальную переменную и сравнивает с нулем. - person Konstantin Raspopov; 13.10.2020
comment
@ Eitanos30, что касается байт-кода Kotlin - его легко увидеть и декомпилировать в более читаемую Java из Android Studio. Просто зайдите в Инструменты- ›Kotlin-› Показать байт-код Kotlin и нажмите «Декомпилировать». - person Konstantin Raspopov; 13.10.2020
comment
Raspopopv, когда вы говорите, что помещает содержимое поля в локальную переменную, вы имеете в виду, что копия объекта сохраняется в локальной переменной? - person Eitanos30; 13.10.2020
comment
@ Eitanos30 он не создает копию, а просто помещает ссылку на тот же объект в локальную переменную. - person Konstantin Raspopov; 13.10.2020
comment
@ Константин Распопов, спасибо большое! я понимаю! - person Eitanos30; 13.10.2020