Kotlinの便利なnull安全と型キャスト

  •  
 
ふみたろう2020年4月27日 - 16:21 に投稿

タグ

はじめに

javaプログラマーは何度もNullPointerExceptionと対面し、そのたびにコードとにらめっこをしてきたことだと思います。 そもそもjavaは参照型を扱う言語であり、null値の参照型変数を参照してしまうと上記の例外を発生させてしまいます。 その例外を根本的に発生させないため、kotlinには予期せぬnullを入れないための概念があります。 それがnull安全という仕組みです。

null 安全

kotlinはデフォルトでnullを許容していません。 そのため、nullを想定するかしないかを(コメントアウトではなく言語レベルで)はっきりと明示させる必要があります。 遅れましたが、つまり null安全とは「ある参照型がnullを許容するかnullを許容しないかを明確に区別させる」仕組みです。 まず、ダメな例をあげてみます。

var s: String = null

var s: String = "hello"
s = null

この 2 例はどちらもnullを代入しようとした段階でコンパイルエラーが発生してしまいます。 さきほども説明しましたが、kotlinはデフォルトでnullを許容していません。(大事なことなので) この場合の「s」は非 Null型 (Non-Null Type) として扱います。 つまりは、「変数sはnull を許容しないString型」として扱われることになります。

では、どうすればい良いのか。 解決方法はとても簡単で、型名の後ろに「?」を付けるだけです。 この方法を用いた良い例をあげます。

var s: String? = null

var s: String? = "hello"
s = null

見てわかるように型名の後ろに「?」を付けただけです。 これだけで「s」はNull許容型 (Nullable Type) として扱います。 ただ、「?」を付けただけですが、「String」と「String?」は別の型として考えます。

ここで気づいた人もいると思いますが、kotlinという言語は明示するまで「nullが存在しない」ということです。

さて、「String」と「String?」は別と言いましたが、Null許容型で宣言した変数の参照も変わります。 方法は同じように変数名の後ろに「?」を付けるだけです。 非Null型、Null許容型の2例を示します。

var s: String = "hello"
println(s.length)   // OK

println(s?.length)  // コンパイルエラー
var s: String? = "hello"
println(s?.length)  // OK

println(s.length)   // コンパイルエラー

非Null型変数にNull許容型変数の代入はできませんが、Null許容型変数に非Null型変数の代入は可能です。

var a: String = "hello"
var b: String? = a  // OK
var a: String? = "hello"
var b: String = a   // コンパイルエラー

先程、非Null型変数にNull許容型変数の代入はできませんと言いましたが、代入を可能にする方法が存在します。 もっと簡単に言うと、Null許容型変数を非Null型として扱うことが可能です。 方法はこれも簡単で、変数名の後ろに「!!」を付けるだけです。

var a: String? = "hello"
var b: Srting = a!! // OK

この例では「b」は非Null型のString型となります。 元々nullを許容してない言語であるkotlinでnullを扱う場合はNull許容型を参照したり、非Null型に代入したりする際にnullチェックを行うことで、nullを明示することが可能です。 今回は条件式 (if文) を用いたnullチェック例を示します。

var s: String? ="hello"
if (s != null) {
  println(s.length) // OK
}

println(s?.length)  // OK

println(s.length)   // コンパイルエラー

このnullチェックではif文のブロック内のみnullを許容していないので、外側での参照は通常通り「?」を付ける必要があります。

以上でnullに関するお話はこの記事では終わりです。

型キャスト

nullチェックのif文に近い機能があります。 任意のブロックを任意の型でキャストする事が可能です。 まずは、ブロック内のみ型キャストする例を示します。

fun sampleFun(obj: Any): Int? {
  if (obj is String) {
    return obj.length // objはString型
  }
  return null         // objはAny型
}

次は、ブロック外を型キャストする例を示します。

fun sampleFun(obj: Any): Int? {
  if (obj !is String)
    return null     // objはAny型

  return obj.length // objはString型
}

最後に、一部ブロック内かつ条件式内で型キャストを行う例を示します。

fun getStringLength(obj: Any): Int? {
  if (obj is String && obj.length > 0)
    return obj.length // objはString型

  return null         // objはAny型
}

最後の例では条件式内でもキャストが反映されていることが分かると思いますが、とても面白い機能ですよね。

まとめ

kotlinはデフォルトでnullが許容されおらず、nullが存在しないことを前提とした言語です。 nullを許容したい場合はnull安全という仕組みに基づいて宣言、操作する方法について説明しました。 また、nullチェックに似た型キャストという仕組みについても説明しました。

この記事を読んで少しでもkotlinに興味を持っていただけたら幸いです。

コメントを追加

プレーンテキスト

  • HTMLタグは利用できません。
  • 行と段落は自動的に折り返されます。
  • ウェブページのアドレスとメールアドレスは自動的にリンクに変換されます。
CAPTCHA
この質問はあなたが人間の訪問者であるかどうかをテストし、自動化されたスパム送信を防ぐためのものです。