KotlinDive

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

データ型(数値、真偽値、配列)

1. Kotlinのデータ型

Kotlinでは、基本的にすべてメンバ関数やプロパティといったものを備えるオブジェクトとして扱われます。
数値型やブール型、文字列型などは実行時にはプリミティブとして扱われますが、 プログラマーとしては通常のクラスと同じように使うことができます。

2. 数値型

数値型はJavaとほとんど同じですが違いもあります。
最大の違いは暗黙型変換がないことです。


fun main(args: Array) {
    val numInt: Int = 100

    // 以下の式はビルドエラーになる
    // val numLong: Long = numInt
}

数値型には次のようなものがあります。。

Type Bit width
Double 64
Float 32
Long 64
Int 32
Short 16
Byte 8

3. 数値リテラル

Kotlinでは8進数はサポートされていません。

10進数 123 (デフォルトはIntで、明示的にLongを指定したい場合は 123L とする)
16進数 0x3F
2進数 0b010111010
浮動小数 123.45 (デフォルトはDoubleで、明示的にFloatにしたい場合は 123.45f/123.45F とする)

また、数値の区切りとしてアンダースコアを利用することができます。


123_000_000
0b00001111_11110000_11000011

4. プリミティブ型と参照型

数値型て特に注意すべき点は、Java Platformの場合、 nullableでない数値型(例えばInt)は自動的にプリミティブ型として扱われますが、nullable(例えばInt?)は参照型になることです。
以下のサンプルコードを確認するとわかりやすいと想います。


fun main(args: Array) {
    val num1: Int = 12345
    val num2: Int = 12345

    println("プリミティブ型 値が同じか確認: ${num1 == num2}") // == は値の比較
    println("プリミティブ型 参照先が同じか確認: ${num1 === num2}") // === は参照の比較

    val numNullable1: Int? = num1
    val numNullable2: Int? = num1

    println("参照型 オブジェクト値が同じか確認: ${numNullable1 == numNullable2}") // == は値の比較
    println("参照型 参照先が同じか確認: ${numNullable1 === numNullable2}") // === は参照の比較
}

プリミティブ型 値が同じか確認: true
プリミティブ型 参照先が同じか確認: true
参照型 オブジェクト値が同じか確認: true
参照型 参照先が同じか確認: false

このように、参照型であるnullable(int?)は値が同じであっても、 インスタンスの実体が別にあるため === で比較するとfalseになります

5. 明示的型変換

Kotlinでは、演算の際にサイズの小さい型から大きい型へ暗黙的に型変換されません。 そのため、明示的に変換する必要があります。


fun main(args: Array) {
    val numInt: Int = 123
    val numLong: Long = 123

    // これは型が違うため、ビルドエラー
    // println("IntとLongの比較: ${numInt == numLong}")

    println("変換して値を比較: ${numInt.toLong() == numLong}")
}

変換して値を比較: true

型を変換するための関数は以下の通りです。


toByte(): Byte
toShort(): Short
toInt(): Int
toLong(): Long
toFloat(): Float
toDouble(): Double
toChar(): Char

3. 真偽値

真偽値はBooleanです(Boolではありません)。
値はtrueとfalseです。
数値型と同じようにnullableの場合は参照型、そうでない場合はプリミティブ型になります。

|| 論理和(遅延評価)
&& 論理積(遅延評価)
! 否定

真偽値の演算である||と&&は遅延評価であるため、 それぞれのオペランドの評価は実際に評価が必要になるまで評価されません(必要になるまで評価を遅延させる)。
たとえば、&&では左辺の評価結果がfalseだった時点で右辺の評価をしなくても全体でfalseになることが確定します。
そうすると、右辺は評価する必要がなくなるため、実行されません。


fun main(args: Array) {
    val num1 = -5
    val num2 = 10

    // 左辺 isPositive(num1) を評価した結果がfalseだった時点で、
    // isPositive(num1) && isPositive(num2) は必ずfalseとなるため
    // 右辺 isPositive(num2) は評価(実行)されない
    if (isPositive(num1) && isPositive(num2)) {
        println("両方とも正です")
    } else {
        println("どちらかが正ではありません")
    }
}

fun isPositive(num: Int): Boolean {
    val ret = num > 0

    if (ret) {
        println("${num}は正です")
    } else {
        println("${num}は正ではありません")
    }

    return ret
}

-5は正ではありません
どちらかが正ではありません

5. 配列

配列はArrayクラスという形でサポートされています。
Arrayクラスはget(index), set(index)関数があります
(次項で説明しますが、これは[]オペレータでアクセスできるということです)。
Arrayクラスはコンストラクタがprivateであるため、直接生成することはできません。
Arrayクラスを生成するにはArrayOf()かArrayNullOf()を利用します。