※本サイトで紹介している商品・サービス等の外部リンクには、アフィリエイト広告が含まれる場合があります。

8-6. 例外処理 (try-catch-finally)

2023年9月13日

概要

Kotlin では、例外が発生する可能性のあるコードを try-catch 文で囲むことによって、例外処理の方法を定義できます。
例外処理は、予期せぬエラーや例外的な状況が発生した場合に、プログラムがクラッシュするのを防ぎ、適切な処理を行うためのメカニズムです。

書式

try-catch-finally 構文は以下のようになります。

try のあと 波括弧 { } で例外が発生する可能性のある文を記載します。
その後、catch (e: キャッチしたい例外) で処理したい例外コードと 波括弧 { } でその際の例外処理を記載します。catch は何個でも記載できます。
最後に finally で、例外の有無に限らず実行したい文を記載します。finally は省略可能です。

try {
   例外が発生する可能性のある文
} catch (e: キャッチしたい例外) {
    文
} catch (e: キャッチしたい例外2){
    文
} finally {
    例外の有無に限らず実行したい文
}
  • try ブロック: 例外が発生する可能性のあるコードを記述します。
  • catch ブロック: try ブロック内で例外が発生した場合に実行されるコードを記述します。 発生した例外の型に応じて、 複数の catch ブロックを記述することができます。各 catch ブロックは、特定の型の例外を捕捉し、対応する処理を実行します。
  • finally ブロック: 例外が発生したかどうかに関わらず、必ず実行されるコードを記述します。 主に、 ファイルのクローズやネットワーク接続の切断など、 リソースの解放に使用されます。

ArrayIndexOutOfBoundsException の例

配列のサイズをこえてアクセスした際に発生する例外 ArrayIndexOutOfBoundsException を意図的に発生させてみた例です。

fun main() {
    val testArray : Array<Int> = arrayOf(1, 2, 3, 4, 5, 6)
    var index : Int = 0

    try {
        for (i :Int in 0..10) { //配列のサイズを超えて参照
            println (testArray[i])
            index = i
        }
    } catch (e: ArrayIndexOutOfBoundsException) {
        println ("配列のサイズを超えています。i = ${index}, ${e.toString()}")
    } catch (e: Exception){
        println ("エラーが発生しました。${e.message}, ${e.toString()}")
    } finally {
        println ("配列のサイズは ${testArray.size} です。")  // finally は例外の有無にかかわらず実行される
    }
}

出力:

1
2
3
4
5
6
配列のサイズを超えています。i = 5, java.lang.ArrayIndexOutOfBoundsException: Index 6 out of bounds for length 6
配列のサイズは 6 です。

FileNotFoundException の例

以下は、ファイル読み込み時の例外処理です。
この例では、try ブロック内でファイルを読み込もうとしています。ファイルが存在しない場合は FileNotFoundException が発生し、対応する catch ブロックでエラーメッセージが表示されます。その他の例外が発生した場合は、一般的な Exception を捕捉する catch ブロックでエラーメッセージが表示されます。finally ブロックでは、例外が発生したかどうかに関わらず、 ファイルリーダーがクローズされます。

import java.io.File
import java.io.FileNotFoundException
import java.io.FileReader

fun readFile(filename: String) {
    var reader: FileReader? = null
    try {
        val file = File(filename)
        reader = FileReader(file)
        // ファイルの読み込み処理
        println(reader.readText())
    } catch (e: FileNotFoundException) {
        println("ファイルが見つかりません: $filename, ${e.message}, ${e.toString()}")
    } catch (e: Exception) {
        println("ファイルの読み込み中にエラーが発生しました: ${e.message}, ${e.toString()}")
    } finally {
        reader?.close() // ファイルリーダーをクローズ
    }
}

fun main () {
    readFile("non_existent_file.txt")
}

出力:

ファイルが見つかりません: non_existent_file.txt, non_existent_file.txt (指定されたファイルが見つかりません。), java.io.FileNotFoundException: non_existent_file.txt (指定されたファイルが見つかりません。)

ネットワーク接続時の例

ネットワーク接続を行う際に、接続エラーやタイムアウトなどの例外が発生した場合の例です。
この例では、try ブロック内でウェブサイトへの接続を試みています。 接続エラーが発生した場合は、対応する catch ブロックでエラーメッセージが表示されます。finally ブロックでは、例外が発生したかどうかに関わらず、ネットワーク接続が切断されます。

import java.net.HttpURLConnection
import java.net.URI
import java.net.URISyntaxException

fun fetchWebsiteContent(urlString: String) {
    var connection: HttpURLConnection? = null
    try {
        val url = URI(urlString).toURL() // URI を使って URL を構築
        connection = url.openConnection() as HttpURLConnection
        connection.requestMethod = "GET"

        if (connection.responseCode == 200) {
            // 接続成功時の処理
            val content = connection.inputStream.bufferedReader().use { it.readText() }
            println(content)
        } else {
            println("接続エラー: ${connection.responseCode}")
        }
    } catch (e: URISyntaxException) {
        println("不正な URL です: ${e.message}, ${e.toString()}")
    } catch (e: Exception) {
        println("ネットワーク接続中にエラーが発生しました: ${e.message}, ${e.toString()}")
    } finally {
        connection?.disconnect() // 接続を切断
    }
}

fun main(){
    fetchWebsiteContent("https://www.iwannacreateapps2.com")
}

出力:

ネットワーク接続中にエラーが発生しました: www.iwannacreateapps2.com, java.net.UnknownHostException: www.iwannacreateapps2.com

参考情報

https://kotlinlang.org/docs/exceptions.html