Kotlin Programming Intermediate - 4

Beautify.log·2022년 1월 25일
0

Kotlin for Android

목록 보기
4/11
post-thumbnail

코틀린 프로그래밍 네번째입니다.

이 포스팅에서는 예외처리와 함수에 대해 다룹니다.

예외처리(Exception)


자바에서의 예외처리

자바에서 try catch를 사용하여 예외가 터지는 곳을 콘솔에서 검출하는 것을 했습니다.

public class Main {
	public static void main(String[] args) {
	    
	    int firstNum = 123;
	    int secondNum = 10;
	    
	    int result;
	    
	    try {
	        result = firstNum / secondNum;
	        System.out.println(result);
	    } catch (Exception e) {
	        System.out.println("Exception!!!");
	        e.printStackTrace();
	    } finally {
	        System.out.println("Program shut down");
	    }
	    
	}
}

firstNumsecondNum으로 나누었을 때 예외없이 처리된다면 result에 계산한 값을 넣어주고 이를 출력한다음 finally 안에 있는 구문이 실행되고 프로그램은 종료됩니다.

그렇지만 secondNum에 0을 넣고 Run하게 되면 어떻게 될까요?

Exception이 발생하면서 catch문 내의 Exception!!!을 출력하고 어디에서 익셉션이 터졌는지 알려줍니다.

이렇게 말이죠.

결국 여기서 알 수 있는 사실은 try문 내부의 구문들은 익셉션이 터지지 않을 때 정상적으로 작동한 후 finally문 내부의 로직을 실행해준 후 프로그램이 종료된다는 것과,

catch문 내부의 구문들은 try문 내부의 로직에서 문제가 발생했을 때 뒤에 나오는 작업을 즉시 중단하고 익셉션이 터졌음을 알려줍니다.

또한 finally 문은 익셉션이 터짐에도 불구하고 최후에 실행할 로직을 넣어줍니다. 물론 생략가능합니다.

코틀린에서의 예외 처리

코틀린에서 익셉션 처리 하는 방법을 살펴보겠습니다.

var x:Int = 123

try {
	x = null!!
	println("x에 정상적으로 대입됨")
} catch (e:Exception) {
	e.printStackTrace()
	println("Exception 발생!!")
}

변수 x에 123이라는 값이 들어있습니다. 이 때 xnull 값을 넣으려고 시도할 것입니다.
그것도 !!를 붙여 아주 강제적으로 말이죠.

이를 시도해보면 아마 잘 되진 않을 것입니다

xnull이 정상적으로 대입되었다면 x에 정상적으로 대입됨이 콘솔에 출력되어야 하지만

결과는 말해줍니다. NullPointerException을 보여주며 콘솔에 출력하라고 선언한 Exception 발생!!을 보여주고 있습니다...

이처럼 코틀린에서 예외처리하는 방법은 자바와 비슷하나, 그 형태가 조금 다른데

catch 뒤에 붙는 소괄호 안쪽에 (Exception e)가 아니라 (e:Exception)의 형태로 들어간다는 것입니다.

코틀린에서는 변수명 + 자료형의 형태를 취하기 때문이라고 보아야 합니다.

또다른 예시를 보면 "익셉션을 던져준다"는 의미로 throw를 사용하고 있습니다.

fun(args:Array<String>) {
    var amount:Int = 1000

    try {
        amount -= 100
        checkAmount(amount)
    } catch (e:Exception) {
        e.printStackTrace()
    }

    println("program end")

}

fun checkAmount(amount:Int) {
    if (amount < 1000) {
        throw Exception("잔고가 $amount(으)로 1000이하 입니다.")
    }
}

우선 amount변수가 1000으로 주어져있고 여기에서 100을 빼준 후 checkAmount 함수로 가서 값이 1000이하인 경우 Exception을 던져주도록 하고 있습니다.

여기에서는 프로그램상 익셉션이 없기 때문에 try 내부 로직이 도중에 멈추고 catch로 넘어가지 않으나 함수를 거쳐 값을 조회, 비교하여 해당 조건이 참일 때 익셉션을 보여주도록 하고 있으므로 다음과 같은 결과가 출력됩니다.


함수


함수란?

함수는 다음 그림과 같이 표현할 수 있습니다.

들어오는 값에 대해 어떤 절차를 거친 후 밖으로 내보내주는 장치 같은 것입니다.

자바에서 살펴봤듯이 들어오는 값의 개수에는 제한이 없으나 나오는 값(return)의 개수는 한 개로 제한됩니다.

또한 나오는 값이 없는 void 형태의 함수도 있었습니다.

코틀린의 함수

코틀린에서 함수는 fun이라는 키워드로 선언하며 함수명을 붙여주고 그 다음으로는 ()에 파라미터를 넣어주고 {}안에 로직을 작성해줍니다.

간단한 예시로 두 개의 숫자를 받아서 더해주는 함수를 만들어보겠습니다.

fun sumInt(x:Int, y:Int) : Int {
	return x + y
}

매개변수로 x, y를 받아서 x + y한 값을 return해줍니다. 이 때 return 값이 정수형이므로 매개변수와 블록 사이에 : Int를 선언하여 반환값이 정수형임을 나타내주었습니다.

이를 람다표현식을 사용해서 더 간단하게 작성해줄 수 있습니다.

fun sumInt(x:Int, y:Int) = x + y

만약 삼항연산자 같은(?) 녀석을 사용해서 x, y 둘 중에 큰 값을 반환해주는 함수를 만든다고 하면

fun maxValue(x:Int, y:Int) = if(x > y) x else y

처럼 사용할 수도 있습니다.

뿐만 아니라 함수의 매개변수에 대해 초기값을 지정해줄 수도 있습니다.

fun sumInt(x:Int = 100, y:Int) : Int {
	return x + y
}

라고 한다면 이 함수에서 y값만 대입하여 사용할 수 있습니다.

println(sumInt(y = 100))

의 결과는 x가 이미 100으로 지정되어 있기 때문에 200으로 출력될 것입니다.

가변 인자란?

가변 인자는 보통의 단일적인 파라미터(xx, yy)가 아닌 n개의 인자를 말합니다. 자바에서는 파라미터에 ...를 넣어 사용했으며 내부적으로 배열을 만든다고 봐도 좋을 것 같습니다.

예를 들어 가변 인자를 사용하는 함수를 만들어보겠습니다.

fun allocParam(vararg counts:Int) {
    for (num in counts) {
        print("$num ")
    }
    print("\n")
}

이 함수를 사용하기 위해서는 다음과 같이 선언할 수 있습니다.

allocParam(1, 2, 3, 4)
allocParam(1, 2, 3, 4, 5, 6, 7)

여기에 들어가는 각각의 파라미터는 개별적인 것이 아니라 하나의 덩어리입니다.

한 가지 중요한 사실은 가변 인자를 사용하기 위해서는 vararg를 선언하고 가변인자의 변수명을 선언해줍니다.

함수의 인자로 함수 사용하기

가령 두개의 함수가 있다고 가정해봅시다.

fun sum(a:Int, b:Int) = a + b

fun funcParam(a:Int, b:Int, c:(Int, Int) -> Int):Int {
    return c(a, b)
}

sum 함수는 두개의 파라미터를 더해서 반환해주는 함수입니다.

그리고 funcParam은 두개의 정수를 파라미터로 받고, 그리고 c라는 매개변수는 두개의 정수를 받아서 하나의 정수로 처리해주는 형태를 가지고 있습니다.

이 때 return값은 c가 되는데, 이 함수를 사용하기 위해서 두개의 정수를 처리해주는 함수 sumfuncParam의 매개변수로 넣어주겠습니다.

println(funcParam(1, 2, ::sum))

함수의 파라미터로 함수를 넣어줄 때는 ::을 붙여서 사용하며 이 때 a값 1과 b 값 2가 sum 함수에 의해 계산되고 이 값을 반환해 줍니다.

결과는 3이 나오게 됩니다.

또한 함수를 일반 변수에 할당하여 사용할 수 있는데, 위에서 예를 든 sum 함수를 다른 변수에 저장해서 사용해보겠습니다.

fun sum(a:Int, b:Int) = a + b

fun main(args: Array<String>) {
	val likeLambda = ::sum
	println(likeLambda(6, 5))
}

처럼 likeLambda라는 변수에 할당하여 이를 다른 이름의 함수로 사용하고 있습니다.

profile
tried ? drinkCoffee : keepGoing;

0개의 댓글