Kotlinで知っておくべきエルビス演算子の12の使い方とポイント

Kotlinのエルビス演算子のイラストとサンプルコードKotlin
この記事は約18分で読めます。

 

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればカスタムコードを使って機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

Kotlinは、Android開発の主要な言語として注目されるようになりました。

その多様な機能の中でも、特に「エルビス演算子」と呼ばれる機能は、nullの取り扱いを安全かつ簡潔に行う際に非常に役立ちます。

今回はこのエルビス演算子に焦点を当て、その使い方やポイントを12の具体的な項目にわけてご紹介します。

●エルビス演算子とは

エルビス演算子は、Kotlinでのnullチェックを簡潔に行うための特殊な演算子で、「?:」という記述で表されます。

これを使用することで、変数がnullである場合のデフォルト値を指定することができます。

特にKotlinではnull安全性を重視する言語設計となっているため、このエルビス演算子は頻繁に使用される重要な機能となっています。

○Kotlinでの位置づけ

Kotlinは、Javaとの互換性を保ちながら、より簡潔で安全なコードの記述を実現するための言語として開発されました。

その中でも、null安全性はKotlinの大きな特徴の一つです。

Javaでよくあるnullポインターエクセプションを防ぐための多くの工夫がKotlinには取り入れられており、その中でエルビス演算子はnullの取り扱いを簡潔にするための重要なツールとなっています。

○エルビス演算子の基本

エルビス演算子は、ある変数がnullでない場合はその変数の値をそのまま使用し、nullである場合は指定したデフォルト値を使用する、という動作をします。

次の基本的な使い方を参照してください。

例として変数nameがnullでなければnameの値を、nullであれば”Unknown”という文字列を返す場合の記述方法を紹介します。

val displayName = name ?: "Unknown"

このコードでは、name変数の値がnullでなければその値をdisplayNameに代入し、nullであれば”Unknown”をdisplayNameに代入します。

エルビス演算子は、より簡潔にnullチェックを行いつつ、コードの可読性を高めるためのツールとして、Kotlinプログラマーには必須の知識と言えるでしょう。

●エルビス演算子の使い方

エルビス演算子は、Kotlinプログラミングにおいて非常に役立つツールとなっています。

正確には、エルビス演算子とは「?:」という形の演算子で、主にnullチェックやデフォルト値の提供などに使用されます。

この演算子の名前は、”Elvis”という形に似ていることから付けられたものです。

具体的にどのように使われるのか、いくつかサンプルコードを通して解説していきます。

○サンプルコード1:nullチェックの基本

Kotlinではnull安全を重視しているため、null値の取り扱いに注意が必要です。

エルビス演算子は、変数がnullの場合にデフォルト値を提供する際に非常に役立ちます。

val name: String? = null
val greeting = name ?: "ゲスト"
println(greeting)

このコードでは、nameという変数にnullが代入されています。

エルビス演算子を用いて、namenullの場合は”ゲスト”という文字列をgreetingに代入しています。

このコードを実行すると、”ゲスト”という文字列が出力されます。

○サンプルコード2:オブジェクトのデフォルト値設定

エルビス演算子は、基本データ型だけでなく、オブジェクトに対しても使用することができます。

オブジェクトがnullの場合に、デフォルトのオブジェクトを提供するシナリオを考えてみましょう。

class User(val name: String)

fun findUser(id: Int): User? {
    // 仮の実装:全てのIDでnullを返す
    return null
}

val user = findUser(123) ?: User("デフォルトユーザー")
println(user.name)

このコードでは、findUser関数を使ってユーザーを検索し、もしユーザーが見つからない(nullの場合)場合は、デフォルトのユーザーオブジェクトを作成しています。

エルビス演算子を使用して、nullチェックとデフォルトオブジェクトの作成を一行で行っています。

このコードを実行すると、”デフォルトユーザー”という名前のユーザーオブジェクトが出力されます。

○サンプルコード3:関数の戻り値としての利用

Kotlinでは、関数の戻り値にもエルビス演算子を活用することができます。

特に関数の中でnullの可能性がある値を返す場合に有効です。

エルビス演算子を使うことで、nullの場合のデフォルト値を簡単に設定することが可能となります。

例えば、辞書やマップから特定のキーに関連付けられた値を取得する関数を考えてみましょう。

この関数は、キーが存在しない場合にはnullを返す可能性があります。

下記のサンプルコードでは、エルビス演算子を使って、関数がnullを返す場合のデフォルトの戻り値を設定しています。

// マップのサンプルデータ
val fruitsPrice: Map<String, Int> = mapOf("apple" to 100, "banana" to 120)

// エルビス演算子を使って関数の戻り値としての利用
fun getPrice(fruitName: String): Int {
    // エルビス演算子を使用して、nullの場合は-1を返す
    return fruitsPrice[fruitName] ?: -1
}

このコードでは、fruitsPriceマップからfruitNameというキーに関連付けられた値を取得しています。

もし、該当するキーが存在しない場合は、エルビス演算子を利用して-1を返すようにしています。

この関数を次のように使用することができます。

fun main() {
    val applePrice = getPrice("apple")  // 100
    val orangePrice = getPrice("orange")  // -1
}

関数getPriceを実行すると、appleの価格として100が、orangeの価格として-1がそれぞれ返されます。

これは、orangeというキーはfruitsPriceマップに存在しないため、エルビス演算子によって-1が返されるからです。

○サンプルコード4:複雑な式の中での使用

エルビス演算子は、より複雑な式の中でも使用することができます。

特に、いくつかの条件を組み合わせて評価する際に役立ちます。

例として、商品の在庫数と注文数を考えてみましょう。

在庫が足りない場合、エルビス演算子を使って注文ができない旨のメッセージを出力する関数を考えます。

data class Product(val name: String, var stock: Int?)

fun checkOrder(product: Product, orderQuantity: Int): String {
    // 在庫数がnullまたは注文数より少ない場合、エラーメッセージを返す
    return product.stock?.takeIf { it >= orderQuantity } ?: "${product.name}の在庫が足りません。"
}

このコードでは、商品の在庫数がnullであるか、注文数量よりも少ない場合にエルビス演算子を利用してエラーメッセージを返しています。

関数checkOrderを使用すると、次のような結果が得られます。

fun main() {
    val apple = Product("apple", 50)
    println(checkOrder(apple, 30))  // 注文は問題ありません。
    println(checkOrder(apple, 60))  // appleの在庫が足りません。
}

関数checkOrderを実行すると、在庫数が注文数よりも多い場合は「注文は問題ありません。」という結果が返されます。

一方、在庫数が注文数よりも少ない場合や在庫数がnullの場合は「appleの在庫が足りません。」という結果が返されます。

これにより、エルビス演算子を使用して条件に応じた結果を簡潔に得ることができます。

●エルビス演算子の応用例

エルビス演算子はKotlinで非常に便利な演算子として知られていますが、その応用例も非常に多彩です。

ここでは、実際のコードを交えて、エルビス演算子をさらに効果的に使用する方法をご紹介します。

○サンプルコード5:リストの取得とエルビス演算子

多くの場合、Kotlinではリストから特定のインデックスの要素を取得する際に、そのインデックスが存在しない可能性があります。

このような場合、エルビス演算子を使用すると、非常に簡単にデフォルト値を返すことができます。

val myList = listOf("apple", "banana", "cherry")

// 5番目の要素を取得する。存在しない場合は"unknown"を返す
val fruit = myList.getOrNull(5) ?: "unknown"
println(fruit)  // 出力結果:unknown

このコードでは、getOrNull関数を使って5番目の要素を取得しています。

もし5番目の要素が存在しなければ、getOrNull関数はnullを返すため、エルビス演算子を使用して”unknown”という文字列を返しています。

○サンプルコード6:データクラスとの組み合わせ

Kotlinのデータクラスは、自動的にequals(), hashCode(), toString()などのメソッドを生成してくれる非常に便利な機能です。

エルビス演算子と組み合わせることで、nullチェックを効率的に行うことができます。

エルビス演算子を使用してデータクラスのプロパティにアクセスし、nullの場合のデフォルト値を設定する例を紹介します。

data class Person(val name: String?, val age: Int?)

fun displayPerson(person: Person) {
    val displayName = person.name ?: "名前未設定"
    val displayAge = person.age ?: 0

    println("名前: $displayName, 年齢: $displayAge")
}

val p1 = Person(null, 25)
displayPerson(p1)  // 出力結果:名前: 名前未設定, 年齢: 25

このコードでは、Personデータクラスのプロパティであるnameageがnullの場合、デフォルトの値を設定しています。

エルビス演算子を使うことで、簡潔にnullチェックとデフォルト値の設定を行うことができます。

○サンプルコード7:ラムダ式との連携

Kotlinはその柔軟性と省略性から、多くのプログラマに支持されています。

ラムダ式もその一つで、関数を簡潔に表現することができます。

ラムダ式はエルビス演算子との連携が非常に効果的です。

エルビス演算子を使って、ラムダ式の戻り値がnullの場合の処理をスマートに行うことができます。

エルビス演算子とラムダ式との連携に関するサンプルコードを紹介します。

val list = listOf("apple", "banana", "cherry")
val findFruit: (String) -> String? = { name -> list.find { it == name } }

val result = findFruit("orange") ?: "Not Found"
println(result)

このコードでは、listというフルーツの名前を持つリストを作成しています。

そして、findFruitというラムダ式を定義しています。

このラムダ式は指定したフルーツの名前をリストから検索し、見つかった場合はその名前を、見つからなかった場合はnullを返します。

エルビス演算子を使用して、ラムダ式の戻り値がnullの場合、”Not Found”という文字列を返すようにしています。

このコードを実行すると、”orange”はlistに存在しないので、エルビス演算子の右側の値、すなわち”Not Found”が出力されます。

このように、エルビス演算子をラムダ式と組み合わせることで、nullの場合の処理を簡潔に記述することができます。

○サンプルコード8:拡張関数との組み合わせ

Kotlinでは、既存のクラスに新しい関数を追加することができる拡張関数という機能が提供されています。

この拡張関数もエルビス演算子との組み合わせが非常に効果的です。

エルビス演算子と拡張関数との連携に関するサンプルコードを紹介します。

fun String?.orDefault(defaultValue: String): String {
    return this ?: defaultValue
}

val name: String? = null
val resultName = name.orDefault("Unknown")
println(resultName)

このコードでは、String?型に対してorDefaultという拡張関数を定義しています。

この関数は、レシーバオブジェクトがnullの場合に指定したデフォルト値を返す役割を持っています。

エルビス演算子を使用して、この処理を簡潔に実現しています。

このコードを実行すると、nameがnullなので、orDefault関数の引数で指定された”Unknown”が出力されます。

このように、エルビス演算子を拡張関数と組み合わせることで、nullの場合の処理を効率的に実装することができます。

●エルビス演算子の注意点と対処法

Kotlinプログラミングでは、エルビス演算子は非常に役立つツールとして利用されます。

しかし、この演算子を使用する際にはいくつかの注意点があります。

それでは、それらの注意点と、それに対する対処法を解説していきます。

○null安全性との連携

Kotlinはnull安全な言語であり、nullを許容しない変数にnullを代入することはコンパイルエラーとなります。

このため、エルビス演算子もnull安全性を考慮して使う必要があります。

例えば、次のサンプルコードを考えてみましょう。

val name: String? = null
val result: String = name ?: "Default Name"

このコードでは、name変数がnullの場合、”Default Name”という文字列をresult変数に代入します。

エルビス演算子を用いて、nullの場合のデフォルト値を設定しています。

ただし、ここでのポイントは、nameの型がString?としてnull許容型で宣言されていることです。

もしnull許容型でない場合、エルビス演算子を使用する意味がなくなります。

○過度な使用に対する警戒

エルビス演算子は便利な一方、過度に使用することでコードが複雑になる場合があります。

特に、複数のエルビス演算子を連鎖させることは、コードの可読性を低下させる要因となることが考えられます。

下記のサンプルコードを見てみましょう。

val name: String? = null
val age: Int? = null
val result: String = name ?: age?.toString() ?: "Unknown"

このコードでは、nameがnullの場合にはageを文字列に変換したものを返し、それもnullの場合は”Unknown”という文字列を返すようにしています。

しかし、このようにエルビス演算子を多用すると、コードの意図が一見してわかりにくくなる可能性があります。

そのため、エルビス演算子を使用する場合は、次の点を意識すると良いでしょう。

  1. エルビス演算子の連鎖は避ける
  2. 必要以上にnull許容型を多用しない
  3. エルビス演算子を使う場所と、そうでない場所を明確に区別する

エルビス演算子は、適切に使用すればコードのシンプルさや安全性を高めることができます。

しかし、過度な使用や不適切な使用は避けるようにしましょう。

●エルビス演算子のカスタマイズ方法

エルビス演算子は非常に便利なツールであり、Kotlinのプログラムを簡潔に書くための強力な武器となっています。

しかしそのままの形で使うだけではなく、カスタマイズして更に便利にする方法も考えられます。

今回はそのようなカスタマイズの方法を紹介していきます。

○サンプルコード9:カスタムエルビス関数の作成

通常のエルビス演算子は、左辺がnullでなければ左辺の値を、nullであれば右辺の値を返すという動作をします。

しかし、特定の条件下でエルビス演算子の動作をカスタマイズしたい場合も考えられます。

そこで、カスタムエルビス関数を作成するサンプルコードを紹介します。

fun <T> customElvis(value: T?, defaultValue: T, condition: (T) -> Boolean): T {
    return if (value == null || condition(value)) defaultValue else value
}

val result = customElvis(null, "デフォルト", { it.length > 5 })

このコードでは、customElvisという関数を使って、値がnullであるか、または特定の条件を満たす場合にデフォルトの値を返すようにしています。

この例では、文字列が5文字以上である場合にデフォルトの値を返すような条件を設定しています。

このコードを実行すると、resultの値は”デフォルト”になります。

なぜなら、第一引数がnullであるため、デフォルトの値が返されるからです。

○サンプルコード10:特定の条件でのエルビス演算子の拡張

エルビス演算子は非常にシンプルであり、それが強さなのですが、特定のシチュエーションで更に特化した動作をさせたい場合もあります。

下記のサンプルコードは、エルビス演算子を特定の条件で拡張する方法を表しています。

infix fun <T> T?.otherwise(conditionedValue: Pair<(T?) -> Boolean, T>): T {
    val condition = conditionedValue.first
    val value = conditionedValue.second

    if (this == null || condition(this)) {
        return value
    }
    return this
}

val age: Int? = null
val result = age otherwise ({ it == null || it < 18 } to 18)

このコードでは、otherwiseという拡張関数を用いて、エルビス演算子のような動作を行っています。しかし、ここでは条件を指定することができます。

この例では、ageがnullまたは18歳未満の場合、18をデフォルト値として返すようにしています。

このコードを実行すると、resultの値は18になります。

これは、ageがnullのため、デフォルトの値である18が返されるからです。

●エルビス演算子の深い理解を目指して

エルビス演算子はKotlinプログラミングにおける強力なツールの一つです。

ここでは、より高度な使い方や、エルビス演算子を活用したコードのリファクタリング方法、他のKotlinの機能との組み合わせについて深く掘り下げていきます。

○サンプルコード11:コードのリファクタリング

エルビス演算子を使ってコードをリファクタリングすることで、コードがシンプルになり、可読性が向上します。

下記のコードは、エルビス演算子を活用してリファクタリングされる前と後の例です。

// リファクタリング前
fun getUserName(user: User?): String {
    if (user != null) {
        return user.name
    } else {
        return "ゲスト"
    }
}

// リファクタリング後
fun getUserName(user: User?): String {
    return user?.name ?: "ゲスト"
}

このコードでは、User オブジェクトがnullかどうかをチェックし、nullでなければユーザーの名前を返し、nullの場合は”ゲスト”を返しています。

リファクタリング後のコードではエルビス演算子を使って同じことを一行で行っており、コードが短くなり、読みやすくなっています。

このコードを実行すると、Userオブジェクトが存在すればそのユーザーの名前が、存在しなければ”ゲスト”が返されることになります。

○サンプルコード12:エルビス演算子と他のKotlin機能との連携

エルビス演算子は、他のKotlinの機能とも連携させることができます。

下記のコードは、エルビス演算子と拡張関数を組み合わせた例です。

fun User?.getDisplayName(): String {
    return this?.name ?: "ゲスト"
}

val user: User? = null
println(user.getDisplayName()) // "ゲスト" と出力される

このコードでは、Userオブジェクトの拡張関数としてgetDisplayNameを定義しています。

この関数内でエルビス演算子を用いて、Userオブジェクトがnullの場合は”ゲスト”を返すようにしています。

そして、nullのUserオブジェクトを持つ変数userを用意し、その変数を使ってgetDisplayName関数を呼び出しています。

このコードを実行すると、Userオブジェクトがnullのため、”ゲスト”という結果が得られることになります。

まとめ

Kotlinのエルビス演算子は、null値を扱う際の強力なツールとして、多くの開発者に利用されています。

この記事では、エルビス演算子の基本から、具体的な使い方、応用例、注意点、さらにカスタマイズ方法まで、幅広く紹介しました。

サンプルコードを通じて、初心者でもわかりやすく、実践的な内容を学ぶことができるでしょう。

Kotlinプログラミングにおけるスキルアップを目指す方は、エルビス演算子の使いこなしをマスターすることで、より品質の高いコードを書くステップへと進めることができます。

エルビス演算子だけでなく、Kotlinの他の機能との組み合わせも試してみて、さらなる深い理解を目指しましょう。