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 deFloatenfloat), ce qui est évidemment fait ici. Une fois ce déballage automatique réussi, la variablevalue(qui est évidemment unfloatprimitif) 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 valeursnullpossiblesAlors, 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 valeursnullsont autorisées ou non, ou comment les gérer lorsqu'elles se produisent.