본문 바로가기
프로그래밍언어/Kotlin

[kotlin] 자주 사용되는 구문

by 가판이 2025. 2. 9.

DTO 생성하기 (POJO/POCO)

data class Customer(val name: String, val email: String)

 

`Customer` 클래스는 다음과 같은 기능들을 제공합니다:

  • 모든 속성들의 getters (그리고 `var` 일 땐 setter 도)
  • `equals()`
  • `hashCode()`
  • `toString()`
  • `copy()`
  • `component1()`, `component2()`, ..., 

함수 인자들에 기본 값 지정하기

fun foo(a: Int = 0, b: String = "") { ... }

 

이렇게 지정해 두면, 호출 할 때 `a`, `b` 없이 `foo()` 라고 호출 할 수 있다.

list 필터링

val positives = list.filter { x -> x > 0 }

 

짧게 하려면

val positives = list.filter { it > 0 }

collection 에서 특정 요소가 존재하는지 확인하기

if ("john@example.com" in emailsList) { ... }

if ("jane@example.com" !in emailsList) { ... }

문자열 보간

println("Name $name")

안전하게 표준 입력 읽기

// 만일, 입력이 정수로 변환할 수 없다면, 문자열을 읽고 null 을 반환한다. 예제: Hi there!
val wrongInt = readln().toIntOrNull()
println(wrongInt)
// null

// 문자열을 읽어서 문자열을 정수로 변환하고 정수를 반환한다. 예제: 13
val correctInt = readln().toIntOrNull()
println(correctInt)
// 13

인스턴스 확인

when (x) {
    is Foo -> ...
    is Bar -> ...
    else   -> ...
}

복잡하게 if/else 체인을 쓰지 않고 `when` 으로 깔끔하게 처리할 수 있다.

읽기 전용 list

val list = listOf("a", "b", "c")

읽기 전용 map

val map = mapOf("a" to 1, "b" to 2, "c" to 3)

map 요소에 접근하기

println(map["key"])
map["key"] = value

map 또는 list 쌍 탐색하기

for ((k, v) in map) {
    println("$k -> $v")
}

`k` 와 `v` 는 map 의 key 와 value 를 읽기 쉽게 사용한것이다. 실제로 구현할 때, `age`, `name` 등이 key 에 사용된다.

게으른 속성

val p: String by lazy { // 이 값은 첫번째 접근시에만 계산되어집니다.
    // 문자열 계산
}

해당 변수가 메모리에 적재 될 때도 `p` 는 어떤 값도 가지고 있지 않다가, 어디선가 `p` 에 접근하게 되면 그 때 구현 된 값이 적용된다.

함수 확장하기

fun String.spaceToCamelCase() { ... }

"Convert this to camelcase".spaceToCamelCase()

이런 식으로 기존에 존재하는 클래스들에 함수를 추가하거나 재정의할 필요 없이 손 쉽게 추가할 수 있다.

싱글톤 생성하기

object Resource {
    val name = "Name"
}

static class 처럼 인스턴스 생성 없이 바로 사용이 가능한 객체

Use inline value classes for type-safe values

@JvmInline
value class EmployeeId(private val id: String)

@JvmInline
value class CustomerId(private val id: String)

if you accidentally mix up `EmplyeeId` and `CustomerId`, a compilation error is triggered.

Note: The @JvmInline annotation is only needed for JVM backends.

추상화 클래스 인스턴스화 하기

abstract class MyAbstractClass {
    abstract fun doSomething()
    abstract fun sleep()
}

fun main() {
    val myObject = object : MyAbstractClass() {
        override fun doSomething() {
            // ...
        }

        override fun sleep() { // ...
        }
    }
    myObject.doSomething()
}

if-not-null 속기

val files = File("Test").listFiles()

println(files?.size) // size is printed if files is not null

files 가 null 일 경우, NPE 가 발생할 텐데, kotlin 은 `?` 를 사용해 짧고 쉬우면서 안전하게 처리할 수 있다. 이게 싫으면 `if/else` 로 null-safe 하게 바꿔줘야한다.

if-not-null-else 속기

val files = File("Test").listFiles()

// For simple fallback values:
println(files?.size ?: "empty") //files 가 null 이면 "empty" 가 출력되고, 그렇지 않으면 files.size 가 출력된다.

// files 가 null 이면 run block 에서 계산되어 반환된 값을 사용.
val filesSize = files?.size ?: run {
    val someSize = getSomeSize()
    someSize * 2
}
println(filesSize)

null 이면 statement 실행하기

val values = ...
val email = values["email"] ?: throw IllegalStateException("Email is missing!")

 

비어있을 수 있는 collection 에서 첫번째 아이템 얻기

val emails = ... // might be empty
val mainEmail = emails.firstOrNull() ?: ""

if/else 로 확인할 필요 없이 안전하게 "" 로 가져올 수 있다.

null 이 아닐 때 실행하기

val value = ...

value?.let {
    ... // execute this block if not null
}

null 이 아닐 때 nullable 한 값에 매핑하기

val value = ...

val mapped = value?.let { transformValue(it) } ?: defaultValue
// defaultValue 는 value 또는 transformValue 결과가 null 일 때 반환된다.

예외가 생겼을 때 반환하기

fun transform(color: String): Int {
    return when (color) {
        "Red" -> 0
        "Green" -> 1
        "Blue" -> 2
        else -> throw IllegalArgumentException("Invalid color param value")
    }
}

try/catch 표현식

fun test() {
    val result = try {
        count()
    } catch (e: ArithmeticException) {
        throw IllegalStateException(e)
    }

    // Working with result
}

if 표현식

val y = if (x == 1) {
    "one"
} else if (x == 2) {
    "two"
} else {
    "other"
}

Unit 을 반환하는 빌더 스타일의 메소드 사용법

fun arrayOfMinusOnes(size: Int): IntArray {
    return IntArray(size).apply { fill(-1) }
}

함수 단일 표현법

fun theAnswer() = 42

 

이와 동일한 것은:

fun theAnswer(): Int {
    return 42
}

 

이것은 효과적으로 다른 사용법들과 결합하여 더 짧은 코드로 구현될 수 있다. 예를 들어 `when` 표현식:

fun transform(color: String): Int = when (color) {
    "Red" -> 0
    "Green" -> 1
    "Blue" -> 2
    else -> throw IllegalArgumentException("Invalid color param value")
}

하나의 객체의 여러개 메서드들을 호출하기

class Turtle {
    fun penDown()
    fun penUp()
    fun turn(degrees: Double)
    fun forward(pixels: Double)
}

val myTurtle = Turtle()
with(myTurtle) { //draw a 100 pix square
    penDown()
    for (i in 1..4) {
        forward(100.0)
        turn(90.0)
    }
    penUp()
}

하나의 객체의 속성들 설정하기

val myRectangle = Rectangle().apply {
    length = 4
    breadth = 5
    color = 0xFAFAFA
}

 

이것은 객체 생성자에 존재하지 않는 속성들을 구성하는데 유용함.

Java 7 의 try-with-resources

val stream = Files.newInputStream(Paths.get("/some/file.txt"))
stream.buffered().reader().use { reader ->
    println(reader.readText())
}

Generic 타입 정보가 필요한 Generic 함수

//  public final class Gson {
//     ...
//     public <T> T fromJson(JsonElement json, Class<T> classOfT) throws JsonSyntaxException {
//     ...

inline fun <reified T: Any> Gson.fromJson(json: JsonElement): T = this.fromJson(json, T::class.java)

두개의 값 교환하기

var a = 1
var b = 2
a = b.also { b = a }

구현이 필요한 코드 표시하기

코틀린 표준 라이브러리는 `TODO()` 함수를 가지고 있음. 그것은 항상 `NotImplementedError` 를 발생시킴. 이 반환 자료형은 `Nothing` 이기에 자료형을 예측할 필요가 없음. 또한 reason 인자에 접근해서 값을 덮어쓸 수 있음. 

fun calcTaxes(): BigDecimal = TODO("Waiting for feedback from accounting")

 

Intellij Idea 의 코틀린 플러긴은 TODO() 의 의미를 이해하고 TODO 도구 창에 코드 위치를 자동으로 추가함.

반응형

'프로그래밍언어 > Kotlin' 카테고리의 다른 글

Kotlin 기본 문법  (0) 2025.02.04