본문 바로가기

# 02/코틀린

[Kotlin] 흐름의 중단과 반환

반응형

흐름 제어

return : 함수에서 결괏값을 반환하거나 지정된 라벨로 이동

break : for나 while의 조건식에 상관없이 반복문을 끝냄

continue : for나 while의 반복문의 본문을 모두 수행하지 않고 다시 조건으로 넘어감



예외 처리문

 - try {...} catch {...} : try 블록의 본문을 수행하는 도중 예외가 발생하면 catch 블록의 본문을 실행

 - try {...} catch {...} finally {...} : 예외가 발생해도 finally 블록 본문은 항상 실행



return으로 값 반환하기

fun add ( a : Int, b : Int ) : Int {

return a + b

println( "이 코드는 실행되지 않습니다." )                                 // 여기에 도달하지 않음

}


return으로 Unit 반환하기

// 1. Unit을 명시적으로 반환

fun hello(name : String) : Unit {

println( name )

return Unit

}


// 2. Unit 이름을 생략한 반환

fun hello (name : String) : Unit {

println( name )

return

}


// 3. return문 자체를 생략

fun hello (name : String) {

println( name )

}



람다식에서 return 사용하기 - InlineLambdaReturn.kt


fun main() {

retFunc()

}


inline fun inlineLambda ( a : Int, b : Int, out : (Int, Int) -> Unit ) {

out ( a, b )


fun retFunc() {

println("start of retFunc")                 // 1

inlineLambda(13, 3) { a, b ->            // 2

val result = a + b

if ( result > 10 )  return            // 3. 10보다 크면 이 함수를 빠져 나감 (4,5 실행안함)

println("result : $result")            // 4. 10보다 크면 이 문장에 도달하지 못함

}

println("end of retFunc")                 // 5

}



람다식에서 라벨 사용


람다식 함수명 라벨이름@ {

...

return@라벨이름

}


fun inlineLambda(a : Int, b : Int, out : (Int, Int) -> Unit) {                 // inline이 제거됨

out(a, b)

}


fun retFunc() {

println("start of retFunc")

inlineLambda(13, 3) lit@{ a, b ->              // 1. 람다식 블록의 시작 부분에 라벨을 지정함

val result = a + b

if ( result > 10 ) return@lit                // 2. 라벨을 사용한 블록의 끝부분으로 반환

println ( "result : $result" )

}                                                       // 3

println("end of retFunc")                         // 4. 이 부분이 실행됨

}



익명 함수의 사용


fun retFunc() {

println("start of retFunc")

inlineLambda(13, 3, fun (a, b) {

val result = a + b

if (result > 10) return

println(""result : $result")

})                                                 // inlineLambda() 함수의 끝

println("end of retFunc")                   // return 되도 실행됨!!

}




람다식과 익명 함수 사용

- 람다식 방법

val getMessage = lambda@ { num : Int ->

if ( num ! in 1..100 ) {

return@lambda "Error"           // 레이블을 통한 반환

}

"Success"                    // 마지막 식이 반환

}



- 익명 함수 방법

val getMessage = fun (num : Int) : String {

if ( num ! in 1..100 ) {

return "Error"

}

return "Success"

}


val result = getMessage(99)





break와 continue

- for나 while, do...while문 루프를 빠져 나옴



for (반복 조건) {

// 본문

...

if ( 중단 조건 ) {

break                // for문 빠져나감 본문2 하지 않음

}

// 본문

}



for (반복 조건) {

// 본문1

...

if ( 중단 조건 ) {

continue                // 본문2를 하지 않고 다시 for문으로!

}

// 본문2

}



NormalBreakContinue.kt


fun main() {

for ( i in 1..5) {

if ( i == 3 ) break

print ( i )

}

println()                 // 개행 문자

println( "outside" )

}



라벨 없는 break와 라벨을 사용한 break


fun labelBreak() {

println( "labelBreak" )

for ( i in 1..5) {

second@ for ( j in 1..5) {

if ( j == 3) break                                  // second@ 빠져나감!

println( "i : $i, j : $j" )

}

println( "after for j" )

}

println( "after for i" )

}



fun labelBreak() {

println( "labelBreak" )

first@ for ( i in 1..5) {

second@ for ( j in 1..5) {

if ( j == 3) break@first

println( "i : $i, j : $j" )

}

println( "after for j" )

}

println( "after for i" )

}




예외(exception)

- 실행 도중의 잠재적인 오류까지 검사할 수 없기 때문에 정상적으로 실행이 되다가 비정상적으로 프로그램이 종료되는 경우

  - 운영체제의 문제 (잘못된 시스템 호출의 문제)

  - 입력값의 문제 (존재하지 않는 파일 혹은, 숫자 입력란에 문자 입력 등)

  - 받아들일 수 없는 연산 (0으로 나누기 등)

  - 메모리의 할당 실패 및 부족

  - 컴퓨터 기계 자체의 문제 (전원 문제, 망가진 기억 장치 등)




예외를 대비하기 위한 구문

try {

예외 발생 가능성 있는 문장

} catch ( e : 예외처리 클래스명 ) {

예외를 처리하기 위한 문장

} finally {

반드시 실행되어야 하는 문장

}


- 반드시 실행해야 할 작업이 없다면 finally 블록은 생략하고 try~catch 블록만으로 코드를 구성할 수 있다.




TryCatch.kt

fun main() {

val a = 6

val b = 0

val c : Int


try {

c = a/b               // 0으로 나눔

} catch ( e : Exception ) {

println ( "Exception is handled." )

} finally {

println ( "finally 블록은 반드시 항상 실행됨" )

}

}


Exception is handled.

finally 블록은 반드시 항상 실행됨




특정 예외 처리

- 산술 연산에 대한 에외를 따로 특정해서 잡을 때

} catch ( e : ArithmeticException) {

println ( "Exception is handled. ${ e.message}" ) 


Exception is handled. / by zero

finally 블록은 반드시 항상 실행됨


- 스택의 추적

} catch ( e : Exception) {

e.printStackTrace()

}


finally 블록은 반드시 항상 실행됨

java.lang.ArithmeticException : / by zero

at com.acaroom.kotlin.chap04.section3.TryCatchKt.main(TryCatch.kt : 9)


- 특정 조건에 따른 예외 발생

throw Exception(message : String)



ThrowExceptionTest.kt

fun main() {

var amount = 600


try {

amount -= 100

checkAmount ( amount )

} catch ( e : Exception ) {

println ( e.message )

}

println( "amount : $amount" )

}


fun checkAmount ( amount : Int ) {

if ( amount < 1000 )

throw Exception( "잔고가 $amount 으로 1000 이하입니다." )

}




사용자 예외 정의

class <사용자 예외 클래스명> (message : String) : Exception( message )


class InvalidNameException (message : String) : Exception(message)     // 1. 사용자 예외 클래스


fun main() {

var name = "Kildong123"                                                      // 2. 숫자가 포함된 이름

try {

validateName( name )

} catch ( e : InvalidNameException ) {                                       // 4. 숫자가 포함된 예외 처리

println( e.message )

} catch ( e : Exception ) {                                                       // 5. 기타 예외 처리

println( e.message )

}

}


fun validateName ( name : String ) {

if (name.matches (Regex(".*\\d+.*"))) {                                    // 3. 이름에 숫자가 포함되어 있으면 예외 던지기

throw InvalidNameException ( "Your name : $name : contains numerals." )

}

}



반응형

'# 02 > 코틀린' 카테고리의 다른 글

[Kotlin] 생성자  (0) 2019.08.06
[Kotlin] 클래스와 객체의 정의  (0) 2019.08.06
[Kotlin] 반복문  (0) 2019.07.18
[Kotlin] MVP Model 구성  (0) 2019.07.15
[Kotlin] MVP 패턴 소개 2  (0) 2019.07.15