Я не могу понять, что ?:
Делает это, например, в этом случае
val list = mutableList ?: mutableListOf()
и почему он может быть изменен для этого
val list = if (mutableList != null) mutableList else mutableListOf()
В дополнение к другим хорошим ответам:
Оператор Elvis является частью многих языков программирования, например, Kotlin, а также Groovy или C #. Я считаю определение Википедии довольно точным:
В некоторых компьютерных языках программирования оператор Элвиса
?:
Является двоичным оператором, который возвращает свой первый операнд, если этот операнд являетсяtrue
, и в противном случае оценивает и возвращает свой второй операнд. Это вариант тернарного условного оператора? :
? :
, найденный на этих языках (и многие другие): оператор Элвиса – это тернарный оператор со вторым операндом, опущенным .
Для Котлина особенно важно следующее:
Некоторые языки компьютерного программирования имеют разную семантику для этого оператора. Вместо того, чтобы первый операнд должен приводить к логическому, он должен приводить к ссылке на объект . Если результирующая ссылка объекта не равна
null
, она возвращается. В противном случае возвращается второй операнд (который может бытьnull
).
Это называется оператором Элвиса, и это точно … То, что вы описали в своем вопросе. Если его левая сторона – это null
значение, вместо этого она возвращает правую сторону, как резервную. В противном случае он просто возвращает значение в левой части.
a ?: b
является просто сокращением, if (a != null) a else b
.
Еще несколько примеров с типами:
val x: String? = "foo" val y: String = x ?: "bar" // "foo", because x was non-null val a: String? = null val b: String = a ?: "bar" // "bar", because a was null
Давайте посмотрим на определение :
Когда у нас есть нулевая ссылка r, мы можем сказать: «Если r не является нулевым, используйте его, иначе используйте некоторое ненулевое значение x»:
Оператор ?:
(Elvis) избегает многословия и делает ваш код очень кратким.
Например, многие функции расширения коллекций возвращают null
качестве резервной копии.
listOf(1, 2, 3).firstOrNull { it == 4 } ?: throw IllegalStateException("Ups")
?:
дает вам способ справиться с резервным случаем elgantely, даже если у вас есть несколько уровней резервного копирования. Если это так, вы можете просто цепью умножить Elvis операторов, как здесь:
val l = listOf(1, 2, 3) val x = l.firstOrNull { it == 4 } ?: l.firstOrNull { it == 5 } ?: throw IllegalStateException("Ups")
Если бы вы выразили то же самое, если бы в противном случае было бы намного больше кода, который сложнее читать.