Kotlinの演算子について

採用はこちら

Kotlinの演算子は、Javaと似ている部分が多い一方で、安全性・明確性・可読性を最優先に設計されています。

そのため「Java経験者ほど誤解しやすいポイント」がいくつも存在します。

本記事では、Kotlinの演算子を単なる一覧ではなく、

  • 実際にどう評価されるのか
  • どこがJavaと決定的に違うのか
  • 誤った理解をしやすい箇所はどこか

という観点で、正確に解説します。

目次

算術演算子(+ – * / %)

Kotlinの算術演算子は基本的にJavaと同じ記号を使います。

val a = 10
val b = 3

a + b  // 13
a - b  // 7
a * b  // 30
a / b  // 3
a % b  // 1

整数除算に注意

Kotlinでも 整数同士の除算は整数 になります。

10 / 3    // 3
10 / 3.0  // 3.333...

暗黙の型変換は存在しない

Kotlinでは数値の暗黙変換が禁止されています。

val d: Double = 10        // コンパイルエラー
val d: Double = 10.0      // OK
val d: Double = 10.toDouble() // OK

これは「安全性を犠牲にして便利さを取らない」というKotlinの設計思想によるものです。

代入演算子(+= -= *= /= %=)

var x = 10
x += 5
x -= 3
x *= 2
x /= 4
x %= 4

重要な注意点(誤解されやすい)

x += y常に x = x + y ではありません。

Kotlinでは次の順序で解決されます。

  1. plusAssign(y) が定義されていれば、それを呼ぶ
  2. 定義されていなければ x = x + yplus(y))に変換

つまり、型によっては 再代入ではなくオブジェクト内部の変更 が起こる場合があります。

この点はJavaよりも柔軟ですが、正しく理解しておく必要があります。

比較演算子(== と === の決定的な違い)

==:構造的等価(値の比較)

a == b

Kotlinの ==null安全 を含んだ比較です。

概念的には次のように評価されます。

a?.equals(b) ?: (b == null)
  • anull でも例外は発生しない
  • equals() による値の比較

===:参照の等価(同一インスタンスか)

a === b
  • メモリ上で同じオブジェクトかどうか
  • Javaの == に相当

val a = String(charArrayOf('t','e','s','t'))
val b = String(charArrayOf('t','e','s','t'))

a == b   // true(値が同じ)
a === b  // false(別インスタンス)

論理演算子(&& || !)

x && y
x || y
!x

短絡評価

KotlinもJavaと同様に短絡評価を行います。

false && function() // function()は呼ばれない
true || function()  // function()は呼ばれない

インクリメント・デクリメント(++ / –)

var x = 10
++x   // 前置
x++   // 後置

制約

  • val には使用不可
  • 式の評価順序はJavaと同じだが、可読性のため乱用は推奨されない

範囲演算子(Kotlinらしさの象徴)

1..5
1 until 5
5 downTo 1
1..10 step 2

for文との組み合わせ

for (i in 1..5) {
    println(i)
}

範囲は IntRange などのオブジェクトとして扱われます。

in / !in 演算子(包含チェック)

val list = listOf(1, 2, 3)

2 in list
5 !in list

範囲・コレクション・文字列など、幅広い型で使用可能です。

null安全演算子(Kotlin最大の特徴)

安全呼び出し演算子 ?.

val name: String? = null
name?.length  // null

Elvis演算子 ?:

val length = name?.length ?: 0
  • 左が null なら右を返す
  • if文を書かずに安全なデフォルト処理が可能

強制アンラップ !!(非推奨)

name!!.length
  • null の場合は 実行時例外
  • Javaとの境界やテストコード以外では極力避ける

型チェックとキャスト

型チェック(スマートキャスト)

if (obj is String) {
    println(obj.length)
}

キャスト

val s = obj as String      // 不一致で ClassCastException
val s = obj as? String    // 不一致で null

as? は安全だが、戻り値は必ず nullable になる点に注意が必要です。

ビット演算(関数として提供)

Kotlinではビット演算は 記号ではなく関数 です。

a and b
a or b
a xor b
a shl 1
a shr 1
a ushr 1
a inv()

これらは infix 関数として定義されています。

演算子オーバーロード(上級者向け)

Kotlinでは特定の関数名を定義することで演算子を使えます。

data class Point(val x: Int, val y: Int) {
    operator fun plus(other: Point): Point {
        return Point(x + other.x, y + other.y)
    }
}

val p3 = p1 + p2

主な対応関係

演算子関数
+plus
minus
*times
/div
[]get / set

== は新しく定義するのではなく、equals をオーバーライドする点に注意。

まとめ

Kotlinの演算子は、

  • null安全を前提
  • 暗黙変換を排除
  • 読みやすさを最優先
  • DSLや拡張を意識した設計

という一貫した思想で作られています。

特に重要なのは次の4点です。

  • ===== の違い
  • ?.?:
  • 範囲・in
  • as? による安全キャスト

これらを正しく理解できれば、Kotlinコードの品質と安全性は大きく向上します。

以上、Kotlinの演算子についてでした。

最後までお読みいただき、ありがとうございました。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次