[kotlin] 예외 처리 (try-catch-finally)

try-catch-finally

    fun main(args: Array<String>){
    	try {
    		println("try top...")
    		val data: String = "Son"
    		val intData: Int? = data.toInt()
    		println("try bottom...")
    	} catch (e: Exception){
    		println("catch...${e.toString()}")
    	} finally {
    		println("finally")
    	}
    }
    
    // try top...
    // catch...java.lang.NumberFormatException: For input string: "Son"
    // finally

catch 문 여러 개

하나의 try 영역에 다양한 예외 처리를 위해 catch 문을 여러 개 작성할 수 있지만, 이때 하위 타입의 예외를 먼저 catch 문으로 선언하고 상위 타입의 예외는 그 다음에 선언해주어야 여러 예외 처리를 수행할 수 있다.

    fun some(args: Array<Any>){
    	try {
    		println("try top...")
    
    		val intData: Int = array[0] as Int
    		
    		val data: String = array[2] as String
    		
    		val data2: Int = data.toInt()
    	} catch (e: ClassCastException) {
    		println("catch...ClassCastException")
    	} catch (e: ArrayIndexOutOfBoundsException) {
    		println("catch...ArrayIndexOutOfBoundsException")
    	} catch (e: Exception){
    		println("catch...${e.toString()}")
    	} finally {
    		println("finally")
    	}
    }
    
    fun main(args: Array<String>) {
    	val array = arrayOf("0", 1, "2")
    	some(array)
    	
    	val array2 = arrayOf(10, "5")
    	some(array2)
    	
    	val array3 = arrayOf(10, 0, "world")
    	some(array3)
    }
    
    // try top...
    // catch...ClassCastException
    // try top...
    // catch...ArrayIndexOutOfBoundsException
    // try top...
    // catch...java.lang.NumberFormatException: For input string: "world"

표현식으로 try-catch 이용

try-catch를 표현식으로 사용하면 각 영역의 마지막 줄이 반환값이다. 이때 finally 문을 함께 사용하면 finally 문은 표현식으로 사용되지 않는다.

    fun some(arg: String): Int {
    	val parseData: Int = try {
    		arg.toInt()
    	} catch (e: Exeption) {
    		0
    	} finally {
    		100 // 사용 안됨
    	}
    	return parseData
    }
    fun main(args: Array<String>) {
    	println("${some("10")}")
    	println("${some("a")}")
    }
    
    // 10
    // 0

예외 발생시키기 throw

예외 발생은 throw 키워드를 이용하며 throw 뒤에 Exception 클래스 객체를 명시하면 해당 예외가 발생한다.

    fun some(arg: String): Int {
    	if(arg < 1) 
    		throw Exception("parameter must be greater than zero")
    	else {
    		var sum = 0
    		for(i in 1..arg){
    			sum += i
    		}
    		return sum
    	}
    }
    fun main(args: Array<String>) {
    	try {
    		println("${some(5)}")
    
    		println("${some(-1)}")
    	} catch (e: Exception) {
    		println("catch...${e.toString()}")
    	}
    }
    
    // 15
    // catch...java.lang.Exception: parameter must be greater than zero

Exception 클래스를 정의할 수 있다.

    class MyException(msg: String): Exception(msg){
    	val errorData: String = "some error data"
    	fun errorFun() {
    		println("errorFun call...")
    	}
    }
    
    fun some(){
    	throw MyException("My Error...")
    }
    
    fun main(args: Array<String>){
    	try{
    		some()
    	} catch(e: MyException){
    		println("${e.toString()}")
    		println("${e.errorData}")
    		e.errorFun()
    	}
    }
    
    // MyException: My Error...
    // some error data
    // errorFun call...

코틀린에서 throw는 일종의 표현식이다. throw 구문을 프로퍼티에 대입할 수 있으며 throw만을 반환하는 함수라면 반환 타입을 Nothing으로 지정할 수 있다.

    fun some1(arg: String): Int {
    	val name: String? = null
    	val s: String = name ?: throw IllegalArgumentException("Name required")
    	println("some1 bottom")
    }
    fun some2(arg: Int): Nothing {
    	if(arg > 0) 
    		throw Exception("some2 exception.. arg > 0 true")
    	else 
    		throw Exception("some2 exception.. arg > 0 false")
    }
    fun main(args: Array<String>) {
    	try {
    		some1()
    	} catch (e: Exception) {
    		println("catch...${e.toString()}")
    	}
    
    	try {
    		some2(10)
    	} catch (e: Exception) {
    		println("catch...${e.toString()}")
    	}
    }
    
    // catch...java.lang.IllegalArgumentException: Name required
    // catch...java.lang.Exception: arg > 0 true

코틀린에는 자바의 throws가 없다. 없앤 이유는 프로그램에서 throws가 꼭 필요하지도 않고 프로그램의 생산성과 품질 향상에 별 도움이 안된다고 판단한 것이다.