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