코틀린 프로그래밍 네번째입니다.
이 포스팅에서는 예외처리와 함수에 대해 다룹니다.
자바에서 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");
}
}
}
firstNum
를 secondNum
으로 나누었을 때 예외없이 처리된다면 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이라는 값이 들어있습니다. 이 때 x
에 null
값을 넣으려고 시도할 것입니다.
그것도 !!
를 붙여 아주 강제적으로 말이죠.
이를 시도해보면 아마 잘 되진 않을 것입니다
x
에 null
이 정상적으로 대입되었다면 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으로 출력될 것입니다.
가변 인자는 보통의 단일적인 파라미터(x
면 x
, y
면 y
)가 아닌 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
가 되는데, 이 함수를 사용하기 위해서 두개의 정수를 처리해주는 함수 sum
을 funcParam
의 매개변수로 넣어주겠습니다.
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
라는 변수에 할당하여 이를 다른 이름의 함수로 사용하고 있습니다.