8-6. 例外処理 (try-catch-finally)
概要
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