Kotlin in Action을 스터디하며 정리한 내용입니다.
저작권에 문제가 될 시, 글을 모두 내리겠습니다.
제가 공부한 내용이 더 많은 분들에게도 도움이 되었으면 좋겠습니다. 부족한 부분은 댓글을 통해서 피드백을 주신다면 언제나 반영하겠습니다. 감사합니다.
책에 대한 링크는 맨 아래에 있습니다.
https://github.com/Kotlin-Android-Study-with-SSAFY/Kotlin_In_Action_1
GitHub - Kotlin-Android-Study-with-SSAFY/Kotlin_In_Action_1: SSAFY 13기 모바일 트랙 구미 5반 "코틀린 인 액션" 스
SSAFY 13기 모바일 트랙 구미 5반 "코틀린 인 액션" 스터디(A). Contribute to Kotlin-Android-Study-with-SSAFY/Kotlin_In_Action_1 development by creating an account on GitHub.
github.com
팀원1 Part
2.1 기본 요소 : 함수와 변수
- 코틀린에서는 타입 선언을 생략해도 된다.
2.1.1 Hello, World!
1️⃣ 함수 선언 시 fun 키워드 사용
fun main(args : Array<String>){
println("Hello, world!")
}
✔️ 함수를 선언할 때는 fun 키워드 사용!!
✔️ fun은 함수임을 나타내며, 그 뒤에 함수 이름과 괄호, 그리고 함수 본문이 온다.
2️⃣ 파라미터 이름 뒤에 파라미터 타입 지정
**fun add(a: Int, b: Int): Int {
return a + b
}**
✔️ 함수 매개변수는 이름과 타입을 콜론(:)으로 구분하여 명시
✔️ 파라미터 이름 뒤에 그 파라미터의 타입을 쓴다.
✔️ 파라미터의 타입이 함수 이름보다 뒤에 오지 않고, 각 매개변수 이름 다음에 바로 붙기 때문에 읽기 쉽고 명확하다.
3️⃣ 최상위 함수 선언(top-level function)
✔️ kotlin은 함수를 반드시 클래스 내부에 선언할 필요가 없다.
✔️ 함수를 최상위 수준에 정의할 수 있다.( 클래스 외부에서 선언할 수 있다는 뜻)
✔️ 파일 내 어디에서나 함수를 선언할 수 있다
✔️ 자바에서는 모든 메서드를 클래스 내부에 넣어야 한다.
// MyUtilities.java
public class MyUtilities {
public static void sayHello() {
System.out.println("Hello from Java!");
}
}
// 사용 예시
public class Main {
public static void main(String[] args) {
MyUtilities.sayHello();
}
}
// MyUtilities.kt
fun sayHello() {
println("Hello from Kotlin!")
}
// 사용 예시
fun main() {
sayHello()
}
4️⃣ 배열도 일반적인 클래스와 마찬가지로 배열 처리를 위한 문법이 따로 존재하지 않는다.
✔️ 배열(Array)이 특별한 자료형이 아니라, 일반적인 클래스(Array<T>
)처럼 동작한다.
5️⃣ System.out.println
대신에 println
을 쓴다.
6️⃣ 줄 끝에 세미콜론(;
)을 붙이지 않아도 된다.
2.1.2 함수
결과를 반환하는 함수의 경우 반환 값의 타입을 어디에 지정해야 할까?
- kotlinc를 실행하면 버전 정보가 표시된 후 >>> 프롬프트 표시
- 입력한 문장이 긑나지 않으면 REPL은 …을 표시해서 뒷부분을 더 입력받는다.
- 두 줄을 넘어가는 경우 >>>와 …을 별도로 표시하지 않을 것이다.
👆🏻if(a > b) a else b
: a 또는 b 값을 결과로 만들어내는 식(expression)
✔️ Kotlin : 삼항 연산자 (?:)가 없음, 이와 같은 방식으로 if를 활용하여 간결하게 값을 결정할 수 있다.
✔️ Java : if가 문(statement)이므로, 직접 값을 반환하지 못하고, 삼항 연산자(?:) 등을 이용해야 한다.
⇒ Kotlin의 if는 결과를 만드는 식이다 ❗
🤔 문(statement)과 식(expression)의 구분
코틀린에서의 if는 식이지 문이 아니다. 식은 값을 만들어 내며 다른 식의 하위 요소로 계산에 참여할 수 있는 반면 문은 자신을 둘러싸고 있는 가장 안쪽 블록의 최상위 요소로 존재하며 아무런 값을 만들어내지 않는다는 차이가 있다.
자바에서는 모든 제어 구조가 문인 반면 코틀린에서는 루프를 제외한 대부분의 제어 구조가 식이다. 제어 구조를 다른 식으로 엮어낼 수 있다면 여러 일반적인 패턴을 아주 간결하게 표현할 수 있다.
1️⃣ 문(statement) : 지시만, 결과값이 나오진 않음, 어떤 일을 수행하는 명령→ Java : if, Kotlin : 대입
int a = 5;
int b = 10;
int max;
// if는 그저 "이렇게 하라!"라고 지시할 뿐 결과값을 만들지 않음
if (a > b) {
max = a;
} else {
max = b;
}
System.out.println("자바에서 최대값은 " + max + "입니다.");
✔️ if ( a > b) 안에서는 “a를 max 안에 넣어!”라고 지시만 한다.
✔️ 그래서 if가 끝난 뒤에야 max에 최종 값이 들어간다.
2️⃣ 식(expression) : 계산을 해서 결과값 만들어냄 → Kotlin에서의 If
val a = 5
val b = 10
// if가 직접 결과를 만들어내므로 한 줄로 끝낼 수 있음
val max = if (a > b) a else b
println("코틀린에서 최대값은 $max 입니다.")
if (a > b) a else b
구문이 “a와 b 중 더 큰 값을 돌려줘!”라는 의미의 식이 됩니다- 그래서 곧바로
val max
에 그 결과값을 담을 수 있어요.
⇒ 반복문(for, while)은 여전히 문으로 취급, 제어 구조가 식으로 작동하면, 여러 가지 로직을 짧고 명확하게 표현할 수 있다.
🤔 대입문은 자바에서는 식이었으나 코틀린에서는 문이 됐다.
✅ Java에서의 실수
boolean flag = false;
if(flag = true) { // 대입문이 식이기 때문에 문법적으로 문제가 없어요.
System.out.println("이 블록은 항상 실행됩니다.");
}
✔️ 여기에서 flag = true 는 대입연산자이지만, 결과로 true를 반환해서 조건무넹 들어가므로, 의도와 다르게 동작된다.
✅ Kotlin에서는 컴파일 에러 발생
var flag = false
if(flag = true) { // 컴파일 에러 발생! -> 대입문은 식이 아니라 문이어서 사용할 수 없다
println("이 블록은 실행되지 않습니다.")
}
✔️ 대입문이 식이 아니므로, 조건문 내에서 대입을 시도하면 문법 오류가 발생해, 버그를 미리 잡을 수 있다.
✔️ 대입문을 식으로 사용하지 않음으로써, 대입과 비교를 헷갈리는 실수를 예방할 수 있다.
🤔 Kotlin은 정적 타입 지정 언어이므로 컴파일 시점에 모든 식의 타입을 지정해야 하지 않나?
정적 타입 지정이란? 컴파일 시점에 변수나 표현식의 타입이 결정되는 방식을 말한다.
식이 본문인 함수의 경우 사용자가 반환 타입을 적지 않아도 컴파일러가 함수 본문 식을 분석해서 식의 결과 타입을 함수 반환 타입으로 정해준다.
2.1.3 변수
✅ Java
✔️ 변수를 선언할 때 타입이 맨 앞에 온다.
int answer = 42
✅ Kotlin
✔️ 타입 지정을 생략하는 경우 흔함
val answer = 42
✔️ 타입으로 변수 선언을 시작하면 타입을 생략할 경우 식과 변수 선언 구별할 수 없음
✔️ 변수 이름 뒤에 타입을 명시하거나 생략하게 허용
val answer: Int = 42
✔️ 부동소수점(floating point) 상수를 사용한다면 변수 타입은 Double이 된다.
val yearsToCompute = 7.5e6 => 7500000.0
→ 만약 float 타입으로 저장하고 싶다면, f 또는 F를 붙여야 함 (val floatValue: Float = 3.14f)
→ float 타입을 명시적으로 적을 필요는 없음
→ double이 기본타입으로 f 생략 가능, float는 f 생략하면 안된다
✔️ 초기화 식을 사용하지 않고 변수를 선언하려면 변수 타입을 반드시 명시해야 한다.
var answer: Int //초기화를 하지 않는 경우 타입을 명시해야 함
answer = 42 //그래야 나중에 값을 할당할 수 있음
→ 초기값이 없으면, 컴파일러가 answer가 어던 타입인지 추론할 수 없기 때문이다!!
✅ 변경 가능한 변수와 변경 불가능한 변수
✔️ val (값을 뜻하는 value에서 따옴) - 변경 불가능한 참조를 저장하는 변수 , val로 선언된 변수는 일단 초기화하고 나면 재대입 불가능 , 자바로 말하면 final 변수
✔️ var(변수를 뜻하는 variable에서 따옴) - 변경 가능한 참조, 변수의 값 바뀔 수 있음
→ 기본적으로 모든 변수를 val 키워드를 사용해 불변 변수로 선언하고 나중에 필요할 때만 var로 변경하기!
→ val 변수는 블록을 실행할 때 정확히 한 번만 초기화돼야 한다.
→ 하지만 어떤 블록이 실행될 때 오직 한 초기화 문장만 실행됨을 컴파일러가 확인할 수 있다면 조건에 따라 val 값을 다른 여러 값으로 초기화할 수도 있다.
ex) 예시 1 : if문을 활용한 초기화
fun example(condition: Boolean): Int {
val value: Int // 초기화되지 않은 변수 선언
if (condition) {
value = 10 // 조건이 true이면 10으로 초기화
} else {
value = 20 // 조건이 false이면 20으로 초기화
}
return value // value는 반드시 초기화된 상태
}
ex) 예시 2 : when문을 활용한 초기화
fun getNumber(type: String): Int {
val num: Int
when (type) {
"one" -> num = 1
"two" -> num = 2
"three" -> num = 3
else -> num = 0
}
return num
}
✔️ var 키워드를 사용하면 변수의 값을 변경할 수 있지만 타입은 고정돼 바뀌지 않는다.
→ 컴파일러는 변수 선언 시점의 초기화 식으로부터 변수의 타입을 추론하며, 변수 선언 이후 변수 재대입이 이뤄질 때는 이미 추론한 변수의 타입을 염두에 두고 대입문의 타입을 검사한다.
✔️ 어떤 타입의 변수에 다른 타입의 값을 저장하고 싶다면 변환 함수를 써서 값을 변수의 타입으로 변환하거나, 값을 변수에 대입할 수 있는 타입으로 강제 형 변환해야 한다.
2.1.4. 더 쉽게 문자열 형식 지정 : 문자열 템플릿
✔️ ${변수}
or $변수
✔️ 문자열 템플릿(String Template) 기능을 제공, 문자열 안에서 변수나 표현식을 간편하게 삽입 가능
fun main ( args : Array<String>) {
if ( args.size > 0) {
println("Hello, ${args[0]}!")
}
}
✔️ 존재하지 않는 변수를 문자열 템플릿 안에서 사용하면 컴파일 오류가 발생한다.
✔️ "$" 문자를 문자열에 넣고 싶으면 println(”\$x”)와 같이 \를 사용해 $를 이스케이프시켜야 한다.
✔️ args 배열의 첫 번째 원소를 넣기 위해 ${ } 구문을 사용한다.
✔️ 중괄호로 둘러싼 식 안에서 큰 따옴표 사용할 수 있다.
✔️ 변수 뿐만 아니라, 표현식(연산, 함수 호출 등)도 $ { } 안에 넣을 수 있다.
fun main() {
val a = 10
val b = 5
println("10 + 5 = ${a + b}")
}
✔️ 문자열 템플릿 안에서도 함수 호출 가능
fun greet(name: String) = "Hello, $name!"
fun main() {
val user = "Alice"
println("${greet(user)} Welcome to Kotlin.")
}
팀원2 Part
2.2 클래스와 프로퍼티
대부분의 경우 자바와 같이 패키지별로 디렉터리를 구성하는 편이 나음
- 특히 자바와 코틀린을 함께 사용하는 프로젝트에서는 자바 방식 따르는게 중요
→ 자바 클래스를 코틀린 클래스로 마이그레이션할 때 문제 발생할 가능성 있음
팀원3 Part
📌 2.3 선택 표현과 처리: enum
과 when
💡
when
은 자바의switch
를 대체하며, 더욱 강력한 기능을 제공한다.
이를 설명하는 과정에서 코틀린에서enum
을 선언하는 방법과 스마트 캐스팅도 함께 살펴본다.
🟢 enum
클래스 정의
enum class Color {
RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET
}
🔹 코틀린의 enum
특징
enum class
사용: 코틀린에서는enum class
를 사용하지만, 자바에서는enum
을 사용한다.- 소프트 키워드:
enum
은 단순한 값 나열이 아니라, 내부에 프로퍼티나 메소드를 정의할 수 있다.
🔹 enum
클래스에 프로퍼티 추가
enum class Color(val r: Int, val g: Int, val b: Int) {
RED(255, 0, 0), ORANGE(255, 165, 0),
YELLOW(255, 255, 0), GREEN(0, 255, 0), BLUE(0, 0, 255),
INDIGO(75, 0, 130), VIOLET(238, 130, 238);
fun rgb() = (r * 256 + g) * 256 + b
}
✅ enum
클래스 활용 시 주의할 점
- 생성자와 프로퍼티를 선언할 수 있다.
- 각
enum
상수를 정의할 때, 프로퍼티 값을 반드시 지정해야 한다. - 메소드를 정의할 경우
enum
상수 목록과 메소드 정의 사이에;
(세미콜론) 필수!
→ 코틀린에서 세미콜론이 필수적인 몇 안 되는 경우 중 하나.
🟠 when
표현식
💡 코틀린에서
when
은if
와 유사하게 값을 반환하는 **표현식(expression) 이다.**switch
문과 달리break
를 사용할 필요가 없으며, 더 유연한 패턴 매칭을 지원한다.
🔹 기본적인 when
사용 예시
fun getMnemonic(color: Color) = when (color) {
Color.RED -> "Richard"
Color.ORANGE -> "Of"
Color.YELLOW -> "York"
Color.GREEN -> "Gave"
Color.BLUE -> "Battle"
Color.INDIGO -> "In"
Color.VIOLET -> "Vain"
}
✅ 자바와 달리 각 분기의 끝에 break
를 명시하지 않아도 된다.
🔹 여러 조건을 하나의 분기로 묶기
fun getWarmOrCold(color: Color) = when (color) {
Color.RED, Color.ORANGE, Color.YELLOW -> "따뜻한 색"
Color.GREEN, Color.BLUE, Color.INDIGO, Color.VIOLET -> "차가운 색"
}
✅ 한 분기에서 여러 값을 매치하려면 ,
(콤마)로 구분하면 된다.
🔹 when
의 다양한 패턴 매칭
fun mixColors(c1: Color, c2: Color): Color? {
return when (setOf(c1, c2)) {
setOf(Color.RED, Color.YELLOW) -> Color.ORANGE
setOf(Color.YELLOW, Color.BLUE) -> Color.GREEN
setOf(Color.BLUE, Color.RED) -> Color.VIOLET
else -> null
}
}
✅ setOf(c1, c2)
를 사용하면 순서에 상관없이 비교 가능!
예를 들어 setOf(Color.RED, Color.YELLOW)
는 setOf(Color.YELLOW, Color.RED)
와 동일한 결과를 반환한다.
🔵 2.3.5 스마트 캐스트: is
를 활용한 타입 검사와 자동 변환
💡
is
키워드를 사용하여 타입을 검사한 후 자동 변환된다.
이를 스마트 캐스트(Smart Cast)라고 한다.
🔹 수식(Expression) 트리 예제
interface Expr
class Num(val value: Int) : Expr
class Sum(val left: Expr, val right: Expr) : Expr
(1 + 2) + 4 같은 연산을 표현하기 위해 트리 구조의 수식(Expression) 클래스를 만든다.
🔹 자바 스타일의 if-else
타입 검사
fun eval(e: Expr): Int {
if (e is Num) {
return e.value
} else if (e is Sum) {
return eval(e.left) + eval(e.right)
} else {
throw IllegalArgumentException("Unknown expression")
}
}
✅ 자바와 다르게 is
검사 후, 명시적인 (Num)e
캐스팅이 필요 없다.
코틀린은 컴파일러가 자동으로 Num
타입으로 변환해준다. (스마트 캐스트)
🔹 when
을 활용한 코드 개선
fun eval(e: Expr): Int = when (e) {
is Num -> e.value
is Sum -> eval(e.left) + eval(e.right)
else -> throw IllegalArgumentException("Unknown expression")
}
✅ when
을 사용하면 코드가 더 간결하고 가독성 좋게 개선된다.
🔵 2.3.7 if
와 when
의 분기에서 블록 사용
💡
if
나when
에서 블록을 사용하면 블록의 마지막 문장이 전체 결과가 된다.
예를 들어eval
함수에서 로그를 추가하려면 각 분기를 블록으로 만들고 마지막에 분기의 결과 값을 위치시키면 된다.
🔹 when
에서 블록 사용하기
fun evalWithLogging(e: Expr): Int =
when (e) {
is Num -> {
println("num: ${e.value}")
e.value
}
is Sum -> {
val left = evalWithLogging(e.left)
val right = evalWithLogging(e.right)
println("sum: $left + $right")
left + right
}
else -> throw IllegalArgumentException("Unknown expression")
}
🔹 실행 결과
>>> println(evalWithLogging(Sum(Sum(Num(1), Num(2)), Num(4))))
num: 1
num: 2
sum: 1 + 2
num: 4
sum: 3 + 4
7
✅ evalWithLogging
함수를 실행하면 연산이 수행된 순서를 확인할 수 있다.
🖼 트리 표현 (그림 2.4)
아래 그림은 Sum(Sum(Num(1), Num(2)), Num(4))
이라는 수식 트리를 표현한 것이다.
✅ 정리
enum class
는 프로퍼티와 메소드를 포함할 수 있다.when
은switch
보다 강력하며,if
처럼 값을 반환하는 표현식이다.when
의 인자를 생략하면Boolean
조건식을 활용할 수 있어 더 유연하다.- 스마트 캐스트(
is
)를 사용하면 타입 검사 후 자동 변환된다. when
에서 블록을 사용하면 마지막 식이 해당 분기의 결과가 된다.evalWithLogging
을 통해when
의 실행 순서를 시각적으로 확인할 수 있다.
📌 참고 이미지
- 수식 트리 표현
- 타입 검사와 스마트 캐스트
팀원4 Part
2.4 대상을 이터레이션: while과 for 루프
- 코틀린 특성 중 자바와 가장 비슷한 것은 이터레이션
- 코틀린 for는 for in 형태 (for-each 루프)
2.4.1 while 루프
- 코틀린에는 while과 do-while 루프가 있음. 두 루프의 문법은 자바와 다르지 않음
2.4.2 수에 대한 이터레이션: 범위와 수열
- 코틀린에는 어떤 변수를 초기화하여 한 번 실행할 때마다 갱신하는 루프(자바의 for 문) 대신 범위(range, 자바의 for-each 문) 를 사용함
val oneToTen = 1..10
- .. 연산자로 시작 값과 끝 값을 연결해서 범위를 만듬
- 범위는 폐구간(닫힌 구간) or 양끝을 포함하는 구간 → 2 번째 값이 항상 범위에 포함됨
- 어떤 범위에 속한 값을 일정한 순서로 이터레이션하는 경우를 수열(progression)이라고 부름
// FizzBuzz 게임 : 우리나라의 369 game과 비슷
fun fizzBuzz(i : Int) = when {
i % 15 == 0 => "FizzBuzz "
i % 3 == 0 => "Fizz "
i % 5 == 0 => "Buzz "
else -> "$i "
}
>>> for (i in 1..100) {
... print (fizzBuzz(i))
...}
}
// 1 2 Fizz 4 Buzz Fizz 7 ...
// -----------------------------------------------------------------------------
// 100 부터 거꾸로 세되 짝수만으로 FizzBuzz 게임 진행
>>> for (i in 100 downTo 1 step 2) {
...print(fizzBuzz(i))
...}
// Buzz 98 Fizz 94 92 FizzBuzz 88 ...
- 증가 값 step 을 갖는 수열에 대해 이터레이션 → 증가 값을 사용하면 수를 건너뛸 수 있음
- 증가 값을 음수로 만들면 역방향 수열을 만들 수 있음 (100 downTo 1 : 역방향 행렬)
- step 2를 붙여 증가 값의 절댓값이 2로 바뀜 ( 방향은 바뀌지 않음 → 실제로는 -2)
- 끝 값을 포함하지 않는 반만 닫힌 범위(half-closed range, 반폐구간) 에 대해 이터레이션
- until 함수 → ( x in 0 until size) 는 (x in 0 .. size-1)와 같음 (until이 좀 더 명확하게 개념을 표현
2.4.3 맵에 대한 이터레이션
// 2진 표현을 map에 저장
// map을 만들고, 몇 글자에 대한 2진 표현으로 map을 채운 다음, 내용 출력
val binaryReps = TreeMap<Char, String>()
for (c in 'A' .. 'F') {
val binary = Integer.toBinaryString(c.toInt()) // ASCII -> 2진 표현
binaryReps[c] = binary // java -> binaryReps.put(c, binary)
}
for ((letter, binary) in binaryReps) {
println("$letter = $binary")
}
// A = 1000001 B = 1000010 C = 1000011 D = 1000100 E = 1000101 F = 1000110
- for 루프를 사용해 이터레이션하려는 컬렉션의 원소를 푸는 방법을 보여줌(map : key/value를 원소를 하는 컬렉션)
- letter : key, binary : 2진 표현(value)
- 이 밖에도 키를 사용해 맵의 값을 가져오거나 키에 해당하는 값을 설정할 수 있음 → get 과 put을 사용하는 대신 map[key]나 map[key] = value를 사용해 값을 가져오고 설정할 수 있음
val list = arrayListOf("10", "11", "1001")
for ((index, element) in list.withIndex()) { // 인덱스와 함께 컬렉션 이터레이션
println("$index: $element")
}
// 0 : 10
// 1 : 11
// 2 : 1001
- 구조 분해 할당(Destructuring Declarations)와 withIndex() 을 이용해 컬렉션을 편하게 이터레이션하는 방법
- 묶인 형태의 데이터( (index, element) )를 한 번에 풀어서 각각의 변수로 받을 수 있음
- 원소의 현재 인덱스를 유지하면서 컬렉션을 이터레이션할 수 있음 → 인덱스 저장을 위한 변수를 따로 만들 필요 없이 깔끔하고 직관적으로 인덱스와 요소를 동시에 다룰 수 있게 됨
2.4.4 in으로 컬렉션이나 범위의 원소 검사
- in 연산자는 어떤 값이 범위에 속하는지 검사할 수 있음 → 반대로 !in을 사용하면 어떤 값이 범위에 속하지 않는지 검사할 수 있음
fun isLetter(c: Char) = c in 'a'..'z' || c in 'A'..'Z' // 'a' <= c && c <= 'z'
fun isNotDigit(c: Char) = c !in '0'..'9'
>>> println(isLetter('q'))
true
>>> println(isNotDigit('x'))
true
- in과 !in 연산자를 when 식에서 사용하도 됨
fun recognize(c: Char) = when (c) {
in '0'..'9' -> "It's a digit!"
in 'a'..'z', in 'A'..'Z' -> "It's a letter!"
else -> "I don't know..."
}
>>> println(recognize('8'))
It's a digit!
- 비교가 가능한 클래스(java.lang.Comparable 인터페이스를 구현한 클래스)라면 그 클래스의 인스턴스 객체를 사용해 범위를 만들 수 있음
>>> println("Kotlin" in "Java".."Scala") // "Java" <= "Kotlin" && "Kotlin" <= "Scala"
true
- String 에 있는 Comparable 구현이 두 문자열을 알파벳 순서로 비교하기 때문에 위 코드의 in 검사에서도 문자열을 알파벳 순서로 비교함
- 컬렉션에도 in 연산을 사용할 수 있음
>>>println("Kotlin" in setOf("Java", "Scala")) // 집합에 "Kotlin"을 포함 x
false
2.5 코틀린의 예외 처리
- 함수는 정상적으로 종료할 수 있지만 오류가 발생하면 예외를 던질 수 있음(throw, 자바와 비슷)
- 발생한 예외를 함수 호출 단에서 처리(catch)하지 않으면 함수 호출 스택을 거슬러 올라가면서 예외를 처리하는 부분이 나올 때까지 다시 던짐(rethrow)
if (percentage !in 0..100) { throw IllegalArgumentException( "A percentage value must be between 0 and 100: $percentage") }
- 자바와 달리 코틀린의 throw는 식이므로 다른 식에 포함될 수 있음
val percentage = if (number in 0..100) number else throw IllegalArgumentException( "A percentage value must be between 0 and 100: $number") // 자바 : (Exception e) {}
2.5.1 try, catch, finally
// 작동 로직은 java와 같음
fun readNumber(reader: BufferedReader): Int? {
try {
val line = reader.readLine()
return Integer.parseInt(line)
}
catch (e: NumberFormatException) {
return null
}
finally {
reader.close()
}
}
>>> val reader = BufferedReader(StringReader("239"))
>>> println(readNumber(reader))
>>> 239
- 자바 코드와 가장 큰 차이는 throws 절이 코드에 없음
- 코틀린은 체크 예외(checked exception)와 언체크 예외(unchecked exception)를 구별하지 않음
2.5.2 try를 식으로 사용
fun readNumber(reader: BufferedReader) {
val number = try {
Integer.parseInt(reader.readLine())
} catch(e: NumberFormatException) {
return
}
println(number)
}
>>> val reader = BufferedReader(StringReader("not a number"))
>>> readNumber(reader) // 아무것도 출력되지 않음
- 코틀린의 try 키워드는 if 나 when 처럼 식이므로 변수에 대입할 수 있음
- try의 본문은 반드시 중괄호로 둘러싸야 함
fun readNumber(read: BufferedReader) {
val number = try {
Integer.parseInt(reader.readLine())
} catch (e: NumberFormatException) {
null // 예외가 발생하면 null 값 호출
}
}
println(number)
}
>>> val reader = BufferedReader(StringReader("not a number"))
>>> readNumber(reader)
null
- try 코드 블록의 실행이 정상적으로 끝나면 그 블록의 마지막 식의 값이 결과
도서 링크 바로가기
https://product.kyobobook.co.kr/detail/S000001804588
Kotlin in Action | 드미트리 제메로프 - 교보문고
Kotlin in Action | 코틀린이 안드로이드 공식 언어가 되면서 관심이 커졌다. 이 책은 코틀린 언어를 개발한 젯브레인의 코틀린 컴파일러 개발자들이 직접 쓴 일종의 공식 서적이라 할 수 있다. 코틀
product.kyobobook.co.kr
'Programming Language > Kotlin' 카테고리의 다른 글
[Kotlin In Action] 1장. 코틀린이란 무엇이며, 왜 필요한가? 스터디 정리 (0) | 2025.02.23 |
---|---|
[Kotlin] BigDecimal 이란 (0) | 2024.05.31 |
[Kotlin] const val에 대해서 공부하자 (0) | 2024.05.28 |
[Kotlin] lateinit, lazy 에 대해서 공부하자 (0) | 2024.05.28 |
[Kotlin] Flow Retry 연산자 (0) | 2024.03.03 |