I understand what Kotlin's !!
operator does. I would like to know if there are any use-cases where it is better to use !!
instead of ?.let
or ?: return
, or some other, safer, null check.
The Kotlin documentation on null safety just says that it is for people who love NullPointerExceptions; why would people want those?
I'm mostly just curious as to whether or not there is a use-case for it, where there isn't a better alternative.
Not everyone is a beginner. Using the exclamation point for this operator helps signify that you better know what you're doing if you do use it.
There are situations where it results in cleaner code. I often see this when working with third-party libraries.
For example, Android's LiveData.value
is nullable, but if you set the value right when you initialize it, then you know the value can never be null.
val myLiveData = MutableLiveData<Float>().apply{ value = 1f }
This is a matter of opinion, but I think it would be very noisy to litter every reference to this getter with an unused default:
when ((myLiveData.value ?: 1f) > 0f) { /* */ }
vs
when (myLiveData.value!! > 0f) { /* */ }
Personally, if I were using the live data from outside the class, I wouldn't use the double bang because then there's no clear guarantee that it actually has a value set. But from within the class containing it, you can trust yourself to know what you're doing.
Here's another example from Android. When you are working within a PreferenceFragmentCompat, and you need to get a Preference reference, you use findPreference
which returns null if the preference is not in the hierarchy. If you know that the Preference should be there, then it makes sense to use !!
because you want to see an exception if it actually isn't there. Alternatively, you could use ?: error("missing preference")
, but it's extra code that doesn't really make it any more obvious in the stack trace what went wrong. Or you might be tempted to use findPreference("x")?.let { //... }
but then it's silently failing when the preference is missing, which is not what you want if you know the preference should be there.
Of course, care should be taken when using !!
. If your particular PreferenceFragment does some manipulation of Preferences by adding and removing them under various circumstances, it might be more appropriate to use ?.let {/**/} ?: Log.e(...)
just in the off-chance during testing you miss a condition where the preference isn't there when you thought it would be.