Java経験者のKotlin Nullableとlet

Java経験者がKotlinを学習していたときに躓いたポイントをメモしておきます。
今回は、Null許容型について。

Nullable


Kotlinのコードを見ているとやけに「?」が多いなと思ったらNull許容型関連のキーワードのようです。
こちらが参考になりました。
Null safety

例えばString型のオブジェクトにnullを入れようとするとコンパイル時にエラーになります。

  1. fun main() {
  2.     var s: String = "symfo"
  3.     s = null
  4.     println(s)
  5.     
  6. }




Null cannot be a value of a non-null type 'kotlin.String'.



nullを許容したい場合は、型名の後に「?」を付けます。

  1. fun main() {
  2.     var s: String? = "symfo"
  3.     s = null
  4.     println(s) // null
  5.     
  6. }



実行結果は「null」と表示されます。

String?に対してlengthで文字列長を取得して見るとコンパイルエラーになります。

  1. fun main() {
  2.     var s: String? = "symfo"
  3.     println(s.length)
  4.     
  5. }




Only safe (?.) or non-null asserted (!!.) calls are allowed



変数名の後に「?」を付けてやると長さが取得できます。

  1. fun main() {
  2.     var s: String? = "symfo"
  3.     println(s?.length) // 5
  4.     
  5. }



sがnullの場合、lengthは評価されず結果はnullとなります。

  1. fun main() {
  2.     var s: String? = "symfo"
  3.     s = null
  4.     println(s?.length) // null
  5.     
  6. }





Elvis operator


nullの場合は文字列長を0としたい場合、こんなよくあるコードになります。

  1. fun main() {
  2.     var s: String? = null
  3.     val l : Int  = if (s != null) s.length else 0
  4.     println(l) // 0
  5.     
  6. }



この場合、エルビス演算子「?:」が便利です。

  1. fun main() {
  2.     var s: String? = null
  3.     val l : Int  = s?.length ?: 0
  4.     println(l) // 0
  5.     
  6. }



評価値がnullでない場合はその値を、nullの場合は演算子以降の式を評価します。
これを利用して、値の代入以外にnullの場合は関数をreturnしたり、エラーを発生させたりも可能です。

  1. fun foo(node: Node): String? {
  2.     // node.getParent()がnullを返したらリターン
  3.     val parent = node.getParent() ?: return null
  4.     // node.getName()がnullならエラーをスロー
  5.     val name = node.getName() ?: throw IllegalArgumentException("name expected")
  6. }





Not-null assertion operator


nullであることをチェックせず強制的に実行する場合は、変数名の後に!!を付与します。

  1. fun main() {
  2.     var s: String? = "Symfo"
  3.     println(s!!.length) // 5
  4.     
  5. }



値がnullの場合は、見慣れたNullPointerExceptionが発生します。

  1. fun main() {
  2.     var s: String? = null
  3.     println(s!!.length) // error
  4.     
  5. }




Exception in thread "main" java.lang.NullPointerException



値のキャストにも利用できます。

  1. fun main() {
  2.     var s: String? = "Symfo"
  3.     var s2: String = s!!
  4.     println(s2.length) // 5
  5.     
  6. }





Let function


letを使用すれば、値がnullでないときのみ処理を実行することができます。
例えばこんな処理。

  1. fun main() {
  2.     val listWithNulls: List<String?> = listOf("Kotlin", null, "Symfo")
  3.     for (item in listWithNulls) {
  4.         if (item != null) println(item) // Kotlin, Symfo
  5.     }
  6. }



letを使用して、以下のように記載できます。

  1. fun main() {
  2.     val listWithNulls: List<String?> = listOf("Kotlin", null, "Symfo")
  3.     for (item in listWithNulls) {
  4.         item?.let {
  5.             println(item) // Kotlin, Symfo
  6.         }
  7.     }
  8. }



itも使用するとこんな感じになりました。

  1. fun main() {
  2.     val listWithNulls: List<String?> = listOf("Kotlin", null, "Symfo")
  3.     for (item in listWithNulls) {
  4.         item?.let {
  5.             println(it) // Kotlin, Symfo
  6.         }
  7.     }
  8. }



関連記事

コメント

プロフィール

Author:symfo
blog形式だと探しにくいので、まとめサイト作成中です。
https://symfo.web.fc2.com/

PR

検索フォーム

月別アーカイブ