最近Kotlinでサーバサイドのプログラムを書いています。
KotlinはJavaをベースに改良された言語ですが、一番の特徴は変数がデフォルトでNull非許容型となっていることでしょう。これによりプログラム内部でNullPointerExceptionが発生することがめったに起こらなくなります。(実際にはJavaのライブラリとの兼合いで発生するケースはあります)
KotlinにはNull非許容型を扱うためJavaにはない構文がいくつか追加されており、最初にコードを読むといささか戸惑うかと思います。
よく使う構文をまとめてみました。
通常の変数
変数は初期化した値から自動で型が決定します。
明示的に型を指定することもでき、その場合はセミコロンのあとに型を記述します。(TypeScriptと同様の構文です)
このようにリテラルを指定した場合、もしくは型を指定した場合は変数はNull非許容型となり、nullを代入しようとするとコンパイルエラーになります。
var test1 = "aaa"
//var test1: String = "aaa" //↑と同じ
test1 = "bbb" // OK
//test1 = null // Compile Error
null許容型
nullを代入できるようにするには型の後ろに”?”を記述します。
var test2: String? = "ccc"
test2 = "ddd" // OK
test2 = null // OK
安全な呼び出し
変数がnullの場合にメソッドを呼び出すとNullPointerExceptionに…なんてことがないように、null許容型の変数からメソッドを呼び出すとコンパイルエラーになります。Kotlinは賢いので。
コンパイルエラーにならないようにするには”.”ではなく”?.”を使用します。この場合、変数がnullの場合はメソッドの呼び出しをスキップします。面白いことに代入時の左辺にもこの演算子が使用できます。
var test3: String? = null
//var test3b = test3.toUpperCase() // Compile Error
var test3b = test3?.toUpperCase() // OK
test3?.toUpperCase()?.toLowerCase()?.length // 複数回呼び出しもOK
class Test3 {
var name: String? = null
}
var test3c: Test3? = null
test3c?.name = test3?.toUpperCase() // 代入もOK(?!)
強制キャスト
nullでないことがわかっている場合に、null許容型からnull非許容型に強制的に変換すればコードが見やすくなります。
この場合は変数のあとに”!!”を記述します。
ただし、値がnullの場合は例外が発生します。
var test4: String? = "eee"
var test4b: String = test4!! // OK
test4 = null
try {
test4b = test4!! // Exception
} catch (ex: Exception) {
System.out.println("test4 is null");
}
自動キャスト
通常、null許容型の変数のメソッドを呼び出す場合は”?.”を使用しますが、先にif文なのでnullチェックをしている場合、以降はnull非許容型にキャストされます。このため”?.”は不要になります。Kotlinは賢いので。
var test5: String? = "fff"
var test5b = ""
if (test5 != null) {
test5b = test5.toUpperCase()
//test5_2 = test5?.toUpperCase() // 上のif文でnullチェックしているため?.は不要
}
Elvis演算子
Kotlinには三項演算子がない(えっ)のでaaa = (aaa != null)? aaa.toUpperCase(): null;のような書き方はできません。
そのかわり、”?:”(Elvis演算子)で変数がnullの場合に別の値を返すことができます。
なお、Elvis演算子には値以外にthrowやreturnも記述できます。
注意点としてif(aaa == null){ throw … } のようにnullチェックと1行の処理を書くとコンパイルで警告が出る場合があります。
この場合はElvis演算子を使用しましょう。
var test6: String? = null
var test6b = test6 ?: "ggg"
System.out.println("test6b=$test6b");
var test6c: String? = null
if (test6c == null) { // Compile Warning
throw Exception("test6d is null")
}
test6c ?: throw Exception("test6c is null") //OK
参考
Null Safety – Kotlin Programming Language
東京都心在住のフルリモート勤務エンジニア。サーバサイドの開発担当で得意な言語はC#。