Kotlinの例外処理でよくある失敗例とその対策まとめ【初心者必見】
生徒
「Kotlinでプログラムが突然止まることがあるんですが、どうすればいいですか?」
先生
「それは例外(エラー)が原因かもしれません。Kotlinでは、例外が発生するとプログラムが止まってしまうことがあります。」
生徒
「例外ってどうやって防げばいいんですか?」
先生
「Kotlinにはtry-catchという例外処理の仕組みがあります。それを正しく使えば、エラーに強いプログラムが書けますよ!」
1. Kotlinの例外処理とは?
Kotlin(ことりん)では、プログラムの実行中に思わぬ問題が起きたとき、そのまま動作が止まってしまうのを防ぐための仕組みとして「例外処理(れいがいしょり)」が用意されています。例外処理は、エラーが発生してもプログラムを安全に続行させたり、原因を分かりやすく伝えるためのとても重要な考え方です。
エラーが起こる場面は、実は日常的なコードの中にもたくさん潜んでいます。たとえば次のようなケースです:
- 存在しないファイルを開こうとした
- 数を0で割ってしまった
- 空のリストから要素を取り出そうとした
- 数値に変換できない文字列を扱ってしまった
こうした問題を無視して処理を進めてしまうと、プログラムが突然停止してしまうことがあります。そこで役立つのが、try と catch を使った例外処理です。あらかじめ「エラーが起きたらどうするか」を決めておくことで、落ち着いて対処できるようになります。
まずは、例外が起きるとどうなるのか、簡単なサンプルで見てみましょう。
fun main() {
val text = "abc" // 数字に見えない文字列
try {
val number = text.toInt() // ここで例外が発生する
println(number)
} catch (e: NumberFormatException) {
println("文字列を数値に変換できませんでした。入力内容を確認してください。")
}
}
文字列を数値に変換できませんでした。入力内容を確認してください。
このように、例外処理を使えば「問題が起きてもプログラムは止まらず、適切なメッセージを表示して処理を続ける」ことができます。初心者のうちから例外処理に慣れておけば、後々より安全で読みやすいコードを書けるようになります。
2. よくある失敗例1:例外処理を忘れる
初心者がつまずきやすいポイントのひとつが、「例外が起こる可能性があるのに、何も対策をしていない」というケースです。普段は正常に動いていても、ちょっとした状況の違いで突然エラーになり、プログラム全体が止まってしまいます。特にリスト操作や文字列の変換などは、小さな油断で例外が発生しやすい代表的な場面です。
fun main() {
val numbers = listOf<Int>() // 中身が空のリスト
println(numbers[0]) // 要素がないため例外が発生する
}
このコードは一見シンプルですが、空のリストから要素を取り出そうとした瞬間にエラーになり、実行が強制的に止まってしまいます。プログラムの動きを「安全に続ける」ためには、例外が発生しうる箇所をしっかり囲っておくことが大切です。
そんなときに役立つのが try-catch です。「問題が起きたらどうするか」を事前に決めておくことで、エラーが出ても落ち着いて処理を続行できます。
fun main() {
val numbers = listOf<Int>()
try {
// ここで例外が起きる可能性がある
println(numbers[0])
} catch (e: IndexOutOfBoundsException) {
// 例外が起きたときの代わりの処理
println("リストが空のため、要素を取得できませんでした。")
}
}
このように書いておけば、例外が発生してもプログラムが途中で止まる心配はありません。初心者のうちは「どこで例外が起きるのか」が分かりにくいですが、まずは「リスト操作」「数値変換」「ファイル操作」などは特に注意する必要がある、と覚えておくとよいでしょう。例外処理は、プログラムを“壊れにくくする”ための重要な習慣です。
3. よくある失敗例2:catchで全部まとめてしまう
次によくあるのが、catchブロックでどんなエラーもまとめてしまう書き方です。
try {
// いろいろな処理
} catch (e: Exception) {
println("何かエラーが発生しました")
}
このように書くと、Exceptionというすべてのエラーの親を受け取ってしまうため、何が問題だったのか判断しづらくなります。
エラーの種類に応じて、適切なcatchを使うのがポイントです。
try {
val text = "123a"
val number = text.toInt()
println(number)
} catch (e: NumberFormatException) {
println("数値に変換できませんでした。")
}
4. よくある失敗例3:finallyの使い忘れ
finallyは、エラーが発生しても発生しなくても、最後に必ず実行されるブロックです。リソースの後片付けなどに使われます。
たとえば、ファイルを開いて何か処理をしたあと、きちんと閉じる必要があります。finallyを使うと安全に片付けができます。
import java.io.File
fun main() {
val file = File("sample.txt")
var reader = file.bufferedReader()
try {
println(reader.readText())
} catch (e: Exception) {
println("ファイルの読み込み中にエラーが発生しました。")
} finally {
reader.close()
}
}
最近ではuse関数を使えば、finallyを使わなくても自動的に閉じてくれるのでおすすめです。
5. よくある失敗例4:catchの中で何もしない
初心者にありがちなのが、catchブロックの中を空にしてしまうことです。
try {
val x = 10 / 0
} catch (e: ArithmeticException) {
}
これだと、エラーが起きても何が起きたのかまったく分かりません。
最低限、printlnでログを出力するようにしましょう。
try {
val x = 10 / 0
} catch (e: ArithmeticException) {
println("0で割ることはできません!")
}
6. よくある失敗例5:例外に頼りすぎる
例外処理はとても便利ですが、なんでもtry-catchで囲むのは逆効果です。
たとえば、リストが空かどうかをチェックせずにtryで囲むより、事前に条件をチェックする方が安全です。
// 良くない例
try {
val name = listOf<String>()[0]
} catch (e: IndexOutOfBoundsException) {
println("名前が取得できませんでした。")
}
// よい例
val names = listOf<String>()
if (names.isNotEmpty()) {
println(names[0])
} else {
println("名前リストが空です。")
}
7. Kotlin初心者が例外処理で気をつけるべきポイント
Kotlinの例外処理では、次のような点に注意することで、エラーに強くてわかりやすいプログラムが書けるようになります。
- 例外が発生しそうな箇所は
try-catchで囲む - エラーの種類に応じた
catchを使う catchの中で何かしらの対応やログを出す- 必要に応じて
finallyでリソースの後片付けを行う - 事前の条件チェックで回避できるエラーは例外に頼らない
これらを意識すれば、初心者でもKotlinの例外処理を正しく使えるようになります。
まとめ
Kotlinの例外処理について学んできた内容を振り返ると、例外は単なるエラーではなく「プログラムが安全に処理を続けるための重要な仕組み」であることがよく分かります。特に初心者がつまずきやすいポイントとして、例外処理を書かないままコードを実行してしまったり、例外を一括で受け取って原因を曖昧にしたり、catchの中で何も処理しないままにしたりする問題が挙げられます。例外処理はプログラムの安全性や可読性に直結するため、ただ囲むだけではなく、意味のある対応を記述することが大切です。 Kotlinではtry-catch-finallyという基本的な構造を使い、発生し得る問題に応じて適切なcatchを配置するのが基本の書き方です。また、ファイルやネットワークなど外部リソースを扱う場合には、finallyで必ずリソースを閉じる処理を書くことが重要になります。さらに最近ではuse関数を活用することで、自動的にリソースを閉じる仕組みが整い、より簡潔で保守性の高いプログラムを書くことができます。 一方で、例外に頼りすぎることは推奨されません。たとえば、リストが空かどうかをチェックせずにIndexOutOfBoundsExceptionを利用して「取得できなかったらcatchで処理すればいい」という書き方は、実装意図を曖昧にし、後から読む人に誤解を与える可能性があります。条件分岐で事前にチェックできる内容は例外に頼らず、例外はあくまで「予測困難なエラー」に備えるために使うことが望ましいです。そのため、設計段階で「どこで例外が発生するのか」「防げるものか」「キャッチすべきか」を整理しながら書く姿勢が重要です。 Kotlinの例外処理は単なるエラー制御にとどまらず、プログラムの品質や信頼性を左右する基盤となっています。たとえばウェブアプリケーションでログイン処理中にサーバーエラーが発生したとき、例外処理によってユーザーに丁寧なメッセージを返すことができれば、サービスの使いやすさが向上します。逆に例外を放置すると、画面が真っ白になったりアプリが強制終了したりと、ユーザー体験が大きく損なわれる可能性があります。このように例外処理は実践的なアプリケーション開発において欠かせない技術と言えるでしょう。 以下では、複数の例外を条件別に処理しつつ、finallyとuseを併用した実践的なサンプルコードを紹介します。実際の開発現場でもよく使われる構造を再現した例になっていますので、ぜひ参考にしてみてください。
複数の例外を使い分けた実践サンプルコード
import java.io.File
fun main() {
val file = File("data.txt")
try {
file.bufferedReader().use { reader ->
val text = reader.readText()
val number = text.toInt()
println("変換した数値: $number")
}
} catch (e: NumberFormatException) {
println("ファイルの内容が数値ではありませんでした。")
} catch (e: java.io.FileNotFoundException) {
println("指定したファイルが見つかりません。")
} catch (e: Exception) {
println("予期しない問題が発生しました。")
} finally {
println("処理を終了します。")
}
}
この例では、ファイルの読み込みから数値変換までの複数工程において起こり得る例外を種類ごとに分けて処理しています。また、useを使うことで、finallyでcloseを明示しなくてもリソース管理が自動的に行われるため、コード全体が簡潔で安全になっています。こうした工夫を積み重ねることで、実践的で信頼性の高いプログラムが書けるようになります。
生徒
「例外処理って難しいイメージがあったけど、種類ごとにcatchを分けたり、useで処理を簡潔にできるのは便利ですね!」
先生
「そうですね。例外処理は単にエラーを防ぐだけでなく、プログラムをより扱いやすくするための仕組みなんです。」
生徒
「例外に頼りすぎず、事前に条件チェックするのも大事なんですね。」
先生
「その通りです。例外は最後の手段として使い、まずは避けられるエラーを防ぐ設計をすることが大切です。」
生徒
「今日の例をアプリ開発でも試してみます!」