Comment écrivez-vous quelque chose comme ça en Java dans Kotlin? Un mémorandum de comparaison de code.
[Kotlin] [Java] Mémo de comparaison Kotlin Java Cet article est spécialisé dans la partie fonction de sécurité Null de.
Je veux connaître les bases de Kotlin en le comparant à Java! Veuillez consulter l'article ci-dessus pour ceux qui le disent.
Il fait référence à un mécanisme qui n'autorise pas Null en principe.
Par exemple, le code suivant
test.kt
val a: String = null
Cela entraînera une erreur de compilation. C'est parce que Kotlin n'autorise pas les valeurs nulles par défaut. Si vous souhaitez autoriser null, ajoutez? Après le type.
test.kt
val a: String? = null //C'est acceptable
Une vérification nulle est toujours requise lors de l'accès à une variable définie avec une option. Comparons-le avec Java.
test.java
String a = null;
a.contains("hoge"); //Naturellement c'est nul, donc ça tombe avec nullpo
test.kt
var a: String? = null
a.contains("hoge") //Il ne compile pas en premier lieu
Cette source de Kotlin est lue au moment de la compilation. C'est parce que non-null n'est pas garanti. Pour accéder aux types Nullable:
test.kt
val a: String? = null
a?.contains("hoge")
Pour les appels de fonction de type Nullable, faites quelque chose comme?. Si a est Null, contient ne sera pas exécuté et Null sera retourné.
Quand j'essaye d'y parvenir avec Java,
Tout d'abord, la vérification Null familière.
test.java
String a = null;
if (a != null) {
a.contains("hoge"); //S'il est nul, il ne passera pas ici
}
Avec Java 8, vous pouvez utiliser la fonction équivalente appelée facultative.
test.java
Optional<String> a = Optional.of(null);
a.ifPresent(notNull -> notNull.contains("hoge")) //contient est exécuté uniquement lorsque le contenu de a n'est pas nul
Vous pouvez voir qu'il peut être écrit de manière très concise par rapport à Java Java n'est qu'une vérification à l'exécution, donc même si vous utilisez Java 8 Facultatif En premier lieu, ce n'est pas une solution fondamentale lorsque vous oubliez d'utiliser Optional. Kotlin est vérifié au moment de la compilation, donc la vérification Null ne sera pas manquée.
Mais les fonctions de sécurité Null de Kotlin ne sont pas non plus parfaites. Par exemple, lors de l'appel d'une méthode Java à partir de Kotlin comme suit
test.kt
var str = System.getProperty("hoge") //str est une chaîne!Moule
Étant donné que Java n'a pas de fonction de sécurité nulle, il est affecté de force en tant que type non nul du côté Kotlin. Si vous forcez une valeur Java à être non nulle, un! Sera ajouté après le type.
C'est un peu délicat et se comporte comme non nul, mais cela pourrait être nul.
test.kt
var str = System.getProperty("hoge")
var strLength = str.length //Parce que ce n'est pas un type Nullable?.Je n'ai pas besoin
Mais bien sûr, getProperty (" hoge ")
peut être retourné comme null, donc strLength peut tomber gluant.
Cela ne signifie pas que la sécurité nulle absolue a été garantie.
Si vous le déclarez explicitement comme type Nullable lors de la réception de la valeur de retour de la méthode Java, il sera de type Nullable.
test.kt
var str: String? = System.getProperty("hoge")
var strLength = str?.length //Parce que c'est un type Nullable?.Est nécessaire
Il est très difficile de gérer cela. .. Si vous souhaitez supprimer complètement Null, vous devez explicitement le rendre Nullable.
Regardons à nouveau l'exemple précédent
test.kt
var str: String? = System.getProperty("hoge")
var strLength = str?.length
Dans ce cas, le type de la variable str est String?
, Donc la strLength à laquelle la valeur de la longueur de str est affectée est ʻInt? `.
En d'autres termes, si le type de la source d'affectation est Nullable, la variable de la destination de l'affectation sera également Nullable.
Avec cela, seules les variables censées être Nullables sont créées et les avantages de la fonction de sécurité Null ne peuvent pas être pleinement exploités.
Si vous souhaitez rendre le type qui était autrefois nullable non nul, il existe les deux méthodes suivantes
test.kt
var str: String? = System.getProperty("hoge")
var foo = str!!.length // !!Vous pouvez forcer str à être de type String en
//foo devient de type Int
Si le type qui est devenu Nullable une fois est !!
,? Sera supprimé.
test.kt
var str: String? = System.getProperty("hoge")
str = str!! //str devient un type String
var foo = str.length // non-Parce que c'est nul?.Ou!!.Aucun opérateur nécessaire
Naturellement, si str est nul, il tombera avec un po gluant. Il est inutile d'en faire un type Nullable.
test.kt
var str = System.getProperty("hoge") ?: "Unknown Property"
var foo = str.length //str devient un type String
Ceci ?:
Est appelé l'opérateur Elvis et évalue l'expression de droite lorsque le résultat de l'expression de gauche de?: Est Null.
test.java
String str = System.getProperty("hoge") != null ? System.getProperty("hoge") : "Unknown Property";
Synonyme de.
Même si Systrem.getProperty ("hoge") est Null, une valeur dédiée est renvoyée à ce moment-là, donc
str devient String type
et foo devient ʻInt type`.
Le type Nullable a disparu et vous pouvez désormais gérer les variables en toute sécurité.
Si vous ne souhaitez pas renvoyer une valeur dédiée, c'est-à-dire si elle est Null, vous ne souhaitez pas continuer le traitement suivant.
test.kt
var str = System.getProperty("hoge") ?: return //str devient un type String
Ensuite, si System.getProperty (" hoge ")
est Null, vous pouvez quitter le traitement de ce bloc.
test.kt
var str = System.getProperty("hoge") ?: return //str devient un type String
En déballant comme ça, il ne tombe plus avec du gluant, Cependant, il n'est pas possible de détecter une erreur simplement en retournant et en quittant le processus sans échouer. En premier lieu, ce code doit supposer que System.getProperty ("hoge") n'obtient pas null.
Si vous souhaitez détecter des retours inattendus sans générer de glu
test.kt
var str = System.getProperty("hoge") ?: run {
println("Property was not found!!!")
return
}
Il est nécessaire de faire cracher une sorte de journal comme ça. L'explication de «run» est omise car elle est hors de cette portée.
Comme Android View, il ne peut pas être initialisé au moment de l'instanciation, Il existe également des cas où il doit être initialisé dans une méthode spécifique telle que ʻonCreate`.
test.kt
class HogeActivity: AppCompatActivity(){
private var textView: TextView? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.hoge_layout)
textView = findViewById(R.id.textView) as TextView
}
}
Puisque textView ne peut être obtenu que s'il est gonflé avec onCreate, La valeur initiale doit être nulle. Dans ce cas, le type sera Nullable comme TextView?.
Il existe deux approches pour rendre ce TextView non nul.
lateinit
est un opérateur pour l'évaluation paresseuse de l'initialisation, et la compilation peut être effectuée sans définir la valeur initiale lors de la définition des variables.
test.kt
class HogeActivity: AppCompatActivity(){
private lateinit var textView: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.hoge_layout)
textView = findViewById(R.id.textView) as TextView
}
}
Il n'est plus nécessaire de définir la valeur initiale en même temps que la déclaration de variable car? Est supprimé du type textView. La valeur est entrée dans textView pour la première fois avec findViewById.
Cependant, il faut faire attention avec lateinit, c'est qu'il ne peut être utilisé que pour des variables (var). Si getter est appelé avant que setter ne soit appelé, il plantera.
L'explication de «par» est un peu compliquée par cela seul, donc je ne vais pas l'expliquer en détail,
Un modificateur qui vous permet de déléguer les paramètres de propriété à une autre classe.
lazy
est une fonction qui est exécutée la première fois que vous accédez à une propriété qui définit lazy.
En combinant les deux, l'initialisation des variables peut être effectuée par n'importe quelle fonction d'une autre classe.
test.kt
class HogeActivity: AppCompatActivity(){
private val textView: TextView by lazy { findViewById(R.id.textView) as TextView }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.hoge_layout)
}
}
De cette façon, lorsque le getter textView est appelé pour la première fois, il sera avant le getter.
findViewById(R.id.textView) as TextView
Est exécuté et la valeur initiale est entrée.
Par lazy, au contraire, ne peut être utilisé que pour les constantes (val). Au lieu de cela, vous n'avez pas à vous soucier de planter comme lateinit.
Si vous pouvez utiliser par paresseux, je pense qu'il vaut mieux l'utiliser. Lateinit est-il utilisé dans des cas tels que le poignard DI, qui est défini par une autre classe?
La sécurité nulle est une fonctionnalité puissante, mais ce n'est pas une solution miracle qui résout tout. Au contraire, on peut dire qu'il empêche la propagation de défauts à d'autres sources car il tombe avec du gluant.
Lorsque vous utilisez la fonction de sécurité Null, je souhaite comprendre le danger qui se cache derrière elle avant de l'utiliser.
Recommended Posts