Kotlinにおける Int 型は、単なる「32bit整数」ではありません。
Javaとの相互運用、JVM最適化、Nullable対応、コレクションとの関係などを正しく理解していないと、意図しないパフォーマンス低下やバグにつながることがあります。
本記事では、Kotlinを実務で使うエンジニア向けにInt 型の仕様と内部挙動を正確に整理し、実践的な注意点まで含めて解説します。
Kotlinの Int 型とは
Int は Kotlin が提供する 32ビット符号付き整数型です。
val a: Int = 10
- ビット数:32bit
- 表現できる範囲:
-2,147,483,648 ~ 2,147,483,647
この数値範囲自体は Java の int と同じですが、Kotlinでは型としての扱い方が異なります。
Kotlinの Int と Javaの int の関係
Kotlinには「プリミティブ型」は存在しない
Kotlinの言語仕様上、int や long といった プリミティブ型は存在しません。
代わりに Int、Long などの Kotlinの数値型を使います。
ただしこれは「常にオブジェクトとして扱われる」という意味ではありません。
JVM上での実際の挙動(重要)
Kotlinコンパイラは、状況に応じて Int を プリミティブ int または java.lang.Integer に変換・最適化します。
| Kotlinコード上の型 | JVM上の実体 |
|---|---|
Int(非Nullable) | int |
Int?(Nullable) | Integer |
ジェネリクス(List<Int>など) | Integer |
val a: Int = 10 // JVMでは int
val b: Int? = 10 // JVMでは Integer
Kotlinの Int は「Kotlinの型」だが、JVM上では最適な形に変換される
この点を正しく理解することが非常に重要です。
数値リテラルと型推論
Kotlinでは、数値リテラルは文脈に応じて型推論されます。
val a = 10 // Int
val b = 10L // Long
val c = 10.0 // Double
可読性のためのアンダースコア
val price = 1_000_000
アンダースコアは コンパイル時に無視されるため、性能への影響はありません。
演算ルールと整数除算
基本演算
val a = 10
val b = 3
val sum = a + b
val div = a / b // 3(整数除算)
Int 同士の割り算は必ず整数除算になります。
小数結果が必要な場合
val div = a.toDouble() / b
意図しない整数除算は、実務で非常に多いバグ原因です。
オーバーフローとアンダーフロー
Kotlinの Int は オーバーフローを検出しません。
val max = Int.MAX_VALUE
println(max + 1) // -2147483648
これは Java と同じく、2の補数によるラップアラウンドです。
実務上の対策
- 計算量が増える可能性がある →
Longを使う - 金額・桁数が重要 → 明示的に範囲チェック
- 例外が欲しい → Javaの
Math.addExact等を利用
Int に用意されている定数・プロパティ
Int.MAX_VALUE
Int.MIN_VALUE
Int.SIZE_BITS // 32
Int.SIZE_BYTES // 4
マジックナンバーを避け、意味のある定数として使えるのは可読性・保守性の面で大きな利点です。
数値型の変換ルール(暗黙変換なし)
Kotlinでは 数値型の暗黙変換は行われません。
val a: Int = 10
val b: Long = a // コンパイルエラー
明示的に変換する
val b: Long = a.toLong()
利用可能な主な変換関数
toByte()
toShort()
toInt()
toLong()
toFloat()
toDouble()
これは 型安全性を高め、バグを防ぐための設計です。
Nullableな Int? の扱い
val a: Int? = null
安全呼び出し
val b = a?.plus(1)
Elvis演算子
val value = a ?: 0
JVM上の重要な注意点
Int?は基本的にIntegerにボックス化される- 頻繁なループや大量データ処理では パフォーマンスコストになる可能性がある
IntArray と List<Int> の違い(実務で非常に重要)
| 型 | JVM上の中身 | 特徴 |
|---|---|---|
List<Int> | Integer | ボックス化あり |
Array<Int> | Integer | ボックス化あり |
IntArray | int | 高速・省メモリ |
val arr = IntArray(5)
arr[0] = 10
数値を大量に扱う処理(集計、ループ、数値演算)では IntArray を優先的に検討すべきです。
演算子は関数として解釈される
Kotlinでは演算子は対応する関数呼び出しとして解釈されます。
val sum = a + b
これは概念的には以下と同等です。
val sum = a.plus(b)
この仕組みにより、ユーザー定義クラスでも演算子オーバーロードが可能になります。
== と === の違い(Int? では特に注意)
val a: Int? = 1000
val b: Int? = 1000
println(a == b) // true(値比較)
println(a === b) // false になることが多い(参照比較)
==:値の比較(equals)===:参照の比較
注意点
Int?はボックス化されるため===は参照比較になる- JVMのキャッシュや最適化により、
===の結果は 環境や状況で変わり得る - 値比較には必ず
==を使う
実務でのベストプラクティスまとめ
- 将来桁が増える可能性がある →
Longを検討 - Nullableは必要最小限に抑える
- 大量数値処理 →
IntArray - 除算は意図を明確に(整数か小数か)
===を数値比較に使わない
まとめ
IntはKotlinの32bit整数型- JVMでは状況に応じて
int/Integerに変換される - Nullable・ジェネリクスではボックス化が発生
- 暗黙の型変換は存在しない
- 大量データでは
IntArrayが有利 - オーバーフローは検出されない
以上、Kotlinのint型についてでした。
最後までお読みいただき、ありがとうございました。










