Kotlin “Smart cast est impossible, parce que la propriété pourrait avoir été modifié en ce moment”
Pourquoi Android Studio afficher le message d'erreur lorsque j'utilise le N ° 2 de script.
Je n'ai trouvé aucune différence entre 1 et 2.
class Adapter {
var nameList : ArrayList<String>? = null
}
class Program {
private fun send() {
val list: ArrayList<String> = ArrayList()
val adapter = Adapter()
//Case 1
var otherList = adapter.nameList
if (otherList != null) {
list.addAll(otherList) //<--- no error
}
//Case 2
if (adapter.nameList!=null) {
list.addAll(adapter.nameList) //<--- Error here
//Smart cast to 'kotlin.collections.ArrayList<String> /* = java.util.ArrayList<String> */' is impossible, because 'adapter.nameList' is a mutable property that could have been changed by this time
}
}
}
Veuillez expliquer ce cas
J'ai ajouté quelques solutions recommandées pour vous ci-dessous.
Double Possible de Smart cast de "Type" est impossible, en raison de "variable" est une mutable biens qui pourraient avoir été modifiés par ce temps
Double Possible de Smart cast de "Type" est impossible, en raison de "variable" est une mutable biens qui pourraient avoir été modifiés par ce temps
OriginalL'auteur quangkid | 2017-10-12
Vous devez vous connecter pour publier un commentaire.
L'IDE devrait vous donner un avertissement, en expliquant que, après le nul de la case, il est possible que
adapter.nameList
a été changé par un autre thread, et que lorsque vous appelezlist.addAll(adapter.nameList)
,adapter.nameList
pourrait en fait être nulle en ce point (encore une fois, parce qu'un autre thread pourrait avoir modifié la valeur. Ce serait une race condition).Vous avez quelques solutions:
Faire
nameList
unval
, qui fait référencefinal
. Puisque c'est définitif, c'est la garantie d'un autre thread ne peut pas le changer. C'est probablement ce qui ne convient pas à votre cas d'utilisation.Créer une copie locale du nom de la liste avant de faire le chèque. Parce que c'est une copie locale, le compilateur sait qu'un autre thread ne peut pas y accéder, et donc il ne peut pas être changé. La copie locale pourrait être défini avec une
var
ou unval
dans ce cas, mais je vous recommande deval
.Utilisez l'une des fonctions de l'utilitaire que Kotlin fournit un tel cas comme cela. La fonction copie la référence qu'il est appelé en tant que paramètre à l'aide d'une fonction en ligne. Cela signifie qu'il efficacement compile vers le bas pour être le même que le n ° 2, mais c'est un peu plus laconique. Je préfère cette solution.
lateinit var
sont limitées à des propriétés de membre, ce qui signifie qu'ils sont déclarés dans la partie supérieure d'une classe. Le sens qu'il ne serait pas déclaré à la portée de tout le code que vous avez écrit, en ce sens qu'elle aurait le même problème.Comment pouvons-nous attribuer une
val
type ? elle n'jeter une erreur?Vous ne pouvez pas réaffecter un
val
type. La définition d'unval
type est qu'il estfinal
, ou qu'il ne peut pas être modifiée.OriginalL'auteur spierce7
Votre adaptateur.liste des passagers est mutable bien merci donc de convertir immuable.
Utiliser cette
Au lieu de cela
Ou vous pouvez également résoudre ce problème en valoir de non-nulle de faire Valoir
Remarque :- !! est évaluée au moment de l'exécution, c'est juste un opérateur.
L'expression (x!!)
jette un KotlinNullPointerException si x == null,
sinon, elle renvoie x jeté à la correspondante de non-type nullable (par exemple, il la retourne comme une Chaîne de caractères lorsqu'il est appelé sur une variable de type Chaîne de caractères?).
C'est une mauvaise pratique. À l'aide de
!!
est vraiment un indicateur que vous avez probablement fait des choses mauvaises. Il est très rare que vous devriez utiliser!!
.ouais, j'ai utilisé !!. même android studio aussi donner le même suggestion à utiliser !!
Si vous déclarez ci-dessus variable comme
val nameList : ArrayList<String>? = null
, n'est-ce pas toujours la valeur null? et il va se planterOriginalL'auteur vishal jangid
La raison de cette case et le message d'erreur est fils. Ce que vous avez appelé une race condition. Dans de nombreux cas analogues, il est possible qu'un autre thread pour modifier la valeur de
adapter.namelist
entre la nullité de vérifier et de l'list.addAll
appel. Manifestement, cela ne peut pas arriver dans votre cas que la carte n'est pas divulgué à partir de la fonction d'envoi, mais je suppose que le compilateur n'est pas assez intelligent pour le savoir.En revanche il n'y a pas de condition de concurrence dans le cas 1 que la liste des passagers n'est accessible qu'une fois.
Aussi cela ne peut pas arriver si
namelist
estval
plutôt quevar
- puisque le compilateur sait alors il ne peut pas changer, alors il ne peut pas changer de non-null null.OriginalL'auteur Michael Anderson