KotlinDive

プログラミング言語 Kotlin についての入門ブログです。

型チェックとキャスト

is

ある変数の実体の型が何であるかを判定するためには「is」演算子を利用します。
is演算子でチェックされた変数は、自動的に判定された型にキャストされます。 これをスマートキャストといいます。


fun main(args: Array) {
    val str = "string"
    val obj: Any = str

    // objはAnyなので次の式はエラーになる
    // obj.length

    // is演算子で型をチェック
    if (obj is String) {
        // 明示的にキャストしなくても、objはStringに自動的にキャストされている
        println(obj.length)
    } else {
        println("obj is not String.")
    }

    // 否定も可能
    // !(obj is String)でもOK
    if (obj !is String) {
        println("obj is not String.")
    } else {
        // 明示的にキャストしなくても、objはStringに自動的にキャストされている
        println(obj.length)
    }

    // whenでも使える
    when (obj) {
        is Int -> println(obj * 2)
        is DoubleArray -> println(obj.average())
        is String -> println(obj.length)
    }
}

6
6
6

as

アンセーフキャスト

as演算子を利用すると、型キャストを行うことができます。
しかし、もしキャストに失敗した場合はClassCastExceptionという例外がスローされてしまいます。 例外は適切に処理されなければ不具合のもとになるため、Kotlinではアンセーフキャストと呼ばれています。


fun main(args: Array) {
    val obj: Any = "some string"

    // objはStringにキャストできる
    val str = obj as String
    println(str.length)

    val obj2: Any = 100

    // ClassCastExceptionが発生してしまう
    var str2 = obj2 as String
    println(str2.length)
}

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
	at ******.main(*******.kt:11)
11

セーフキャスト

一方で、「as?」演算子でnull安全の仕組みを利用して安全なキャストをすることができます.
こちらは、キャストしようとしてできなかった場合、nullが返ります。
つまり、そもそも適切に処理をしないとビルドエラーになり、実行することができません。
プログラマコンパイラによって、きちんとnullチェックをすることが強制され、 うっかりによるチェックもれを防ぐことができるので「安全」だということです。


fun main(args: Array) {
    val obj: Any = "some string"

    // objはStringにキャストできる
    val str = obj as? String
    // strはString?であるため、nullチェックをしないと関数を呼べない
    // 下記のコードはビルドエラーになる
    // println(str.length)
    if (str != null) {
        println(str.length)
    } else {
        println("str is null")
    }

    val obj2: Any = 100

    // ClassCastExceptionが発生してしまう
    var str2 = obj2 as? String
    if (str2 != null) {
        println(str2.length)
    } else {
        println("str2 is null")
    }
}

11
str2 is null