Разница между!! а также? в Котлине

Я новичок в Kotlin. Я хочу знать разницу между этими двумя !! и ? в приведенном ниже коде.

У меня есть ниже двух фрагментов, сначала использующих !! для mCurrentDataset, а другой - ? для той же переменной.

if(!mCurrentDataset!!.load(mDataSetString.get(mCurrentDataSelectionIndex), STORAGE_TYPE.STORAGE_APPRESOURCE))
{
    Log.d("MyActivity","Failed to load data.")
    return false
}

if(!mCurrentDataset?.load(mDataSetString.get(mCurrentDataSelectionIndex), STORAGE_TYPE.STORAGE_APPRESOURCE)!!)
{
    Log.d("MyActivity","Failed to load data.")
    return false
}

Спасибо заранее.

Ответ 1

Как сказано в ссылка Kotlin, !! является опцией для любителей NPE:)

a!!.length

вернет ненулевое значение a.length или выбросит NullPointerException, если a is null:

val a: String? = null
print(a!!.length) // >>> NPE: trying to get length of null

a?.length

возвращает a.length, если a не null, а null иначе:

val a: String? = null
print(a?.length) // >>> null is printed in the console

Подводя итог:

+------------+--------------------+---------------------+----------------------+
| a: String? |           a.length |           a?.length |           a!!.length |
+------------+--------------------+---------------------+----------------------+
|      "cat" | Compile time error |                   3 |                    3 |
|       null | Compile time error |                null | NullPointerException |
+------------+--------------------+---------------------+----------------------+

Может быть полезно: Что такое NullPointerException?

Ответ 2

это '!!' оператор double-bang всегда возвращает не-нулевое значение, и это '?' оператор безопасного вызова возвращает значение, если значение не равно null, а null в противном случае

Это небезопасное преобразование типа NULL (T?) в непустой тип (T). Он выкинет NullPointerException, если значение равно null.

Документировано здесь вместе с средствами Kotlin нулевой безопасности.

ref - горячая клавиша

Ответ 3

приоритет операторов !, ?., !! равен ?. > !! > !.

оператор !! будет поднимать KotlinNullPointerException при работе с ссылкой null, например:

null!!;// raise NullPointerException

оператор безопасного вызова ?. возвращает null при работе с ссылкой null, например:

(null as? String)?.length; // return null;

оператор !! в вашем втором подходе может поднять NullPointerException, если левая сторона null, например:

mCurrentDataset?.load(..)!!
    ^-------------^
           | 
when mCurrentDataset== null || load() == null a NullPointerException raised.

вы можете использовать оператор elvis ?: вместо оператора !! в вашем случае, например:

!(mCurrentDataset?.load(..)?:false)