https://kotlinlang.org logo
Title
d

dG

11/11/2019, 10:30 AM
if (someArray[x] != null) { someArray[x].add(foo) }
Why does the compiler not recognize that
someArray[x]
cannot be null, and insists on
!!
?
k

karelpeeters

11/11/2019, 10:33 AM
Do why mean why it doesn't recognize that
someArray[x]
is not null? The compiler is very conservative about smartcasting, for example in this case another thread might have modified the array inbetween.
m

marstran

11/11/2019, 10:36 AM
You can do
someArray[x]?.let { it.add(foo) }
.
d

dG

11/11/2019, 11:45 AM
@karelpeeters in this case, that wouldn't be possible, as I define the
someArray
right before the if statement. Would checking if other threads have access to the variable not be an option for the compiler?
@marstran thanks, unfortunately I cannot, because I also need an
else
(where
someArray[x]  = mutableList()
)
m

marstran

11/11/2019, 11:48 AM
Then I would just do this:
val list = someArray[x] ?: mutableListOf()
list.add(foo)
someArray[x] = list
d

dG

11/11/2019, 11:53 AM
Thanks. I think the if/else solution is a bit more readable, however
t

thymecypher

11/11/2019, 1:30 PM
public operator fun get(index: Int): E
Since it returns a non-nullable type, you will only ever receive the object at the given index or I believe a
IndexOutOfBoundsException
- it’s equal to
someArray.get(<index>)
To get a null from the accessor you need to either use
list.getOrNull(index)
or
List<(your type)?>
The first, you will get null if the index is out of bounds or if the type is nullable AND the value at the given index is null. The second, you will still get an out of bounds error if the index is out of bounds but if the value at that index is null, you will get a null. The second should be avoided - as it’s best practices to avoid nullable types whenever possible.
That said though, the pattern you seem to be using isn’t good for lists. You can only set
someArray[x]
if
someArray
is at least x long. For example,
val list = mutableListOf(1,2,3)
list[3] = 2
will produce an
IndexOutOfBoundsException
k

karelpeeters

11/11/2019, 2:01 PM
No he's talking about an
Array<T?>
and the fact that the compiler doesn't smartcast elements.
d

Derek Peirce

11/12/2019, 3:27 AM
Even though you defined
someArray
right before this statement, the compiler doesn't know if the method used to generate
someArray
kept a reference to that array and is mutating it in another thread. It was probably a library method that would never do something like that, but the compiler shouldn't know that.
👍 1