Je reçois
java.lang.NullPointerException: tentative d'appel d'une méthode virtuelle 'float java.lang.Number.floatValue ()' sur une référence d'objet nulle
sur le code suivant:
val localHistory: ArrayList<Float> = ArrayList<Float>() ... val strHistory = localHistory.map { value -> decoration.decoratedValue(ref.format, value) }
Je viens d'apprendre que ArrayList peut contenir des valeurs nulles (oookay). Cela voudrait dire que la valeur dans la fermeture de transformation de carte peut être NULL, non?
Mais cela ne peut pas être puisque la valeur n'est pas un type optionnel et le compilateur dit que if (value! = null) sera toujours vrai.
La question est donc de savoir comment éviter les NPE dans ce cas?
3 Réponses :
Si vous souhaitez simplement exclure les valeurs nulles dans la ArrayList
, appelez mapNotNull
au lieu de map
. Voir ici pour plus de détails. Vous devez également gérer le cas où la valeur
est nulle dans votre lambda, ce que vous pouvez faire avec le ? .let
comme indiqué ci-dessous:
localHistory.mapNotNull { value -> value?.let { decoration.decoratedValue(ref.format, it) } }
Je reçois la suggestion du compilateur que ce n'est pas nécessaire lorsque j'essaye d'utiliser mapNotNull
Changez la déclaration en ArrayList
pour indiquer au compilateur que la liste peut contenir des entrées nulles.
Je suggère de marquer chaque paramètre d'une Collection
que vous recevez de Java comme nullable (à moins bien sûr que vous ne le sachiez ne peut jamais être nul
:
val strHistory = localHistory .mapNotNull { decoration.decoratedValue(ref.format, it ?: return@mapNotNull null) }
Ensuite, vous pouvez filtrer les null
et faire votre opération de carte:
val newFloats: List<Float> = floats .mapNotNull { it?.plus(1) }
Gardez à l'esprit que chaque opération filter
, map
(et ainsi de suite) itérera toute la collection et en créera une nouvelle à chaque fois. Il vaut mieux utiliser Sequence code > s, qui sont itérés paresseusement.
Comme mentionné dans les commentaires, on peut utiliser filterNotNull
pour filtrer directement toutes les valeurs nulles:
val newFloats: List<Float> = floats .filterNotNull() .map { it + 1 }
Notez également que vous pouvez utiliser filterNotNull ()
au lieu de filter {it! = Null}
.
Un autre avec mapNotNull:
val strHistory = localHistory.mapNotNull { it ?: return@mapNotNull null decoration.decoratedValue(ref.format, it) }
Comment remplissez-vous la
ArrayList
? le faites-vous en kotlin ou en java?Bonne question. Il est en fait désérialisé par GSON donc ce devrait être Java
Bien entendu, la liste peut contenir
null
. Dans ce cas, le déballage automatique échouera (conversion deFloat
enfloat
), ce qui est évidemment fait ici. Une fois ce déballage automatique réussi, la variablevalue
(qui est évidemment unfloat
primitif) ne peut plus êtrenull
.Le Json peut-il contenir des valeurs
null
? Si oui, marquez la collection que vous obtenez de java commeArrayList
, puis filtrez les valeursnull
possiblesAlors, quelles sont mes options pour éviter que cela échoue?
Je ne connais pas Kotlin. En Java brut, vous pouvez filtrer les éléments
null
:localHistory.stream (). Filter (Objects :: nonNull) .map (...)
. Mais peut-être devriez-vous d'abord clarifier si les valeursnull
sont autorisées ou non, ou comment les gérer lorsqu'elles se produisent.