Kotlin 제어 구문(Control statement)
조건문(Conditional statement)
if 문
if(expr) stmt1 else stmt2
는 만약 expr
이 참이면, stmt1
을 그렇지 않으면 stmt2
을 실행한다.
if (a > b) {
println("Big")
} else {
println("Small")
}
main 함수에 args
가 비어 있지 않으면 받은 인수에 따라 문자열을 변경하도록 해보자. 조건에 따라 처리를 분기하는 구문은 Java에서도 인숙한 if-else
이다.
예제: args가 비어 있지 않은지 확인
fun main(args: Array<String>) {
if (args.isNotEmpty()) {
println("Hello, ${args[0]}!")
} else {
println("Hello, world!")
}
}
isNotEmpty
메서드는 배열이 비어 있지 않은지 확인한다. 배열이 비어 않다면, isNotEmpty
에서 true
를 반환하고 if
다음에 오는 블록을 실행한다. 그렇지 않으면 else
다음에 오는 블록을 실행한다. Java의 if-else
와 마찬가지로 분기 후에 블록 내의 문장이 하나인 경우에만 중괄호({ }
) 를 생략하여 작성할 수 있다.
Kotlin에서 if-else
는 식이다. if-else
는 값을 반환한다.
var c = if (a > b) a else b
이는 자바의 삼항 연산자와 같은 동작을 한다. 위에 예제를 다시 작성하면 아래와 같이 된다.
예제: if-else
는 수식이다.
fun main(args: Array
코틀린에서는 삼항식 연산식이 없고, 위와 같이 if
문으로 표현해야 한다.
Java에서는 삼항 연산자를 (condition) ? a : b
와 같이 작성하는데, Kotlin에서는 삼항 연산자를 지원하지 않는다.
반복문(Loop Control)
for 루프
for 루프문 기본 형태는 for (... in ...) ...
이고, 범위나 배열, 컬렉션을 반복할때 사용된다.
for (i in 1..10) {
println(i)
}
for (i in 10 downTo 0 step 2) {
println(i)
}
var colors = arrayOf("Red", "Green", "Blue")
for (color in colors) {
println(color)
}
main 함수에 여러 개의 커멘드 라인 인수에 대해 모두 Hello
를 출력하고 싶다면, for
루프를 사용한다.
예제: args
의 각 요소에 Hello를 반복한다.
fun main(args: Array<String>) {
for (name in args) {
println("Hello, ${name}!")
}
}
Kotlin for
은 Java의 “확장 for 문” 과 유사하다. 루프 카운터를 늘려가는 스타일의 루프를 Kotlin for은 지원하지 않는다.
forEach 루프
forEach
와 forEachIndexed
는 배열이나 컬렉션에 대해서 처리를 반복한다.
var a = arrayOf("Red", "Green", "Blue")
a.forEach {
value -> println(value)
}
a.forEachIndexed {
index, value -> println("${index}: ${value}")
}
아래 예제는 목록 여러 형태로 반복하여 출력하는 프로그램이다.
ForTutorial.kt
fun main() {
val langList = listOf("javascript", "python", "kotlin", "java", "go")
println("========= for loop =============");
for (item in langList) {
println(item)
}
println("========= for loop index =============");
for (index in langList.indices) {
println("${index} = ${langList[index]}")
}
println("========= for each loop =============");
langList.forEachIndexed { index, value ->
println("$index = $value")
}
}
Output:
========= for loop =============
javascript
python
kotlin
java
go
========= for loop index =============
0 = javascript
1 = python
2 = kotlin
3 = java
4 = go
========= for each loop =============
0 = javascript
1 = python
2 = kotlin
3 = java
4 = go
for문은 iteration한 값을 반복할 수 있다.
for (item in list)
라고 하면 list에 값을 하나하나 꺼내와 item
변수에 받아 올 수 있다.
for (index in list.indices)
라고 작성하면 item이 몇번째에 위치하는 인덱스 값은 idx
변수에 받아 올 수 있다. 인덱스를 받아오기 때문 list[index]
에 접근하여 해당하는 값을 가져올 수도 있다.
forEachIndexed()
메소드를 사용하면 index
와 value
를 같이 받아올 수 있다. 자바에서는 따로 변수를 만들어 증가 연산자를 넣어주여 하지만, 코틀린에서는 이 메소드로 해결이 가능하다.
while 루프
while
은 조건이 성립되는 동안 작업을 반복한다.
var i = 10
while (i > 0) {
println(i--)
}
while
을 활용한 코드는 아래와 같다.
WhileTutorial.kt
fun main(args:Array<String>) {
val mostLang = listOf("javascript", "python", "kotlin", "java", "go")
println("== while case 1 ==============")
var i = 0
while (true) {
if (i == mostLang.size) {
break
}
println(mostLang[i])
i++
}
println("== while case 2 ==============")
var j = 0
while (j < mostLang.size) {
println(mostLang[j])
j++
}
}
== while case 1 ==============
javascript
python
kotlin
java
go
== while case 2 ==============
javascript
python
kotlin
java
go
do-while 루프
do ... while
은 조건이 성립되지 않을 때까지 루프를 반복한다.
var i = 10
do {
println(i--)
} while (i > 0)
분기문(Branching statement)
break 문
break
는 가장 안쪽의 루프를 빠져 나온다.
for (i in 1..5) {
if (i == 2) {
break
}
println(i)
}
continue 문
continue 가장 안쪽의 루프에 다음 반복을 시작한다.
for (i in 1..5) {
if (i == 2) {
continue
}
println(i)
}
when 식
when
은 조건에 따라 다른 값을 반환한다. is
문으로 데이터 타입에 따라서 처리를 배분할 수 있다.
fun describe(obj: Any): String =
when (obj) {
1 -> "One"
in 2..3 -> "Two or Three"
"Hello" -> "Greeting"
is Long -> "Long"
!is String -> "Not a string"
else -> "Unknown"
}
switch case
문과 비슷하게 보이지만 약간 다른다. 보통 switch
문에서 case
는 한가지 타입만 들어가야 하는데, when
에서는 모든 타입이 다 들어갈 수 있다. 로직이 완료되고 break
문을 넣어서 빠져나올 필요도 없다. 해당 조건에 맞으면 바로 빠져 나오게 된다. default
대신에 else
를 사용한다.
WhenTutorial.kt
fun whenFunc(value: Any) {
when (value) {
0 -> println("0 입니다.")
"two" -> println("two 입니다.")
3.14 -> println("3.4 입니다.")
else -> println("아무것도 해당되지 않아요")
}
}
fun main(args: Array<String>) {
whenFunc(0)
whenFunc("two")
whenFunc(3.14)
whenFunc(1234)
}
0 입니다.
two 입니다.
3.4 입니다.
아무것도 해당되지 않아요
그밖에
레이블(@)
@
으로 레이블을 지정함으로써, break
와 continue
의 대상 루프를 지정할 수 있다.
foo@ for (i in 1..5) {
for (j in 1..5) {
if (i == 3 && j == 3) break@foo
println("$i $j")
}
}
함수의 람다 식으로 return
하면 일반적으로 함수에서 반환되지만 @
레이블 지정하여 람다 식을 return
하는 것이 가능하다.
fun foo() {
listOf(1, 2, 3, 4, 5).forEach baa@ {
if (it == 3) return@baa
println(it) // 1, 2, 4, 5
}
}
클래스나 함수는 암시적으로 클래스명, 함수명의 레이블을 가지고 있다. 아래와 같이 내부 클래스에서 외부 클래스의 인스턴스를 참조하는 것도 가능하다.
class A {
val foo = "AAA"
inner class B {
val foo = "BBB"
fun foo() = println("${this.foo} ${this@A.foo}") // BBB AAA
}
}
fun main() {
A().B().foo()
}
예외 처리 (try, throw, catch, finally)
예외 처리는 다음과 같은 예이다.
try {
if (...) {
throw IllegalStateException()
} catch (e: Exception) {
println(e)
} finally {
println("Finally")
}
}
try
는 예외 처리를 시작한다. throw
예외를 던진다. catch
는 예외를 잡는다. finally
는 예외 발생과 상관 없이 기술된 처리를 무조건 실행한다.