Kotlin

    [Kotlin] @JvmRecord 사용해 자바의 record 클래스 정의하기

    자바의 Record 클래스 Java 14부터 Record라 불리는 데이터를 저장하는 클래스가 도입됐다. 이 Record는 코틀린의 Data class와 매우 유사한 기능으로, 'record' 키워드로 선언된 클래스는 equals, hashCode, toString 함수를 자동으로 생성한다. 예를 들어 다음과 같이 생성된 record 클래스 Blog가 있다고 해보자. *아래 코드는 Java이다. public record Blog(String name, int age) { } 이 Blog 클래스는 이름(name)과 생긴 후 지난 날짜(age)를 인자로 받는다. 이제 이 record 클래스가 어떻게 동작하는지 확인하기 위해 다음과 같이 코드를 만들어보자. public class Main { public st..

    [Kotlin] 제네릭 사용 시 Cannot check for instance of erased type: T 오류 해결 방법 : inline과 reified를 사용한 문제 해결

    Cannot check for instance of erased type: T 오류는 왜 발생할까? JVM은 제네릭 타입을 실행 시점에 지원하지 않기 때문에, 자바의 제네릭과 마찬가지로 코틀린의 제네릭 또한 컴파일 타입에 타입 지워짐(Type Erasure)이 발생한다. 이 때문에 제네릭을 사용하는 일반 함수에서는 함수 본문에서 제네릭 타입을 이용해 연산을 할 수 없다. 예를 들어 다음과 isType 함수를 살펴 보자. fun isType(value: Any): Boolean { return value is T } 이 함수는 겉보기에는 문제가 없어 보인다. 하지만, T라는 타입은 컴파일 시점에 지워지고, 실행 시점에는 T가 무슨 타입인지 알 수 없기 때문에 다음과 같은 오류가 발생한다. Cannot ch..

    [Kotlin] inline fun 함수를 사용한 고차 함수 최적화

    함수의 매개 변수로 람다식을 받을 경우의 문제 일반적으로 함수를 호출하면 해당 함수가 서브루틴으로써 실행된다. 반면 inline fun으로 선언된 함수를 호출하면, 함수 호출을 실행하는 것이 아니라 해당 함수가 호출된 위치에 함수 내부의 코드가 삽입돼 실행된다. 예를 들어 다음과 같은 코드가 있다고 해보자. fun main(args: Array) { printWorldAfterFunction { println("Hello") } } fun printWorldAfterFunction(function: () -> Unit) { function() println("World") } 이 코드에서 printlnWorldAfterFunction 함수를 () -> Unit 타입의 람다식과 함께 실행하면, () -> ..

    [Kotlin] operator fun 을 통한 연산자 오버로딩 한번에 정리하기

    operator fun이란 코틀린은 특정한 부호의 연산을 함수로 정의할 수 있는 연산자 오버로딩 기능을 제공한다. 예를 들어 plus 라는 함수를 operator fun으로 선언하면 + 연산과 같은 효과를 낸다. 예를 들어 다음 Vector 클래스를 살펴보자. data class Vector(val x: Float, val y: Float) { operator fun plus(vector: Vector): Vector { return Vector(this.x + vector.x, this.y + vector.y) } } 이 Vector 클래스는 operator fun plus을 선언하고 있으며, 이 함수는 두 Vector를 더할 때 x 값은 x 값끼리, y 값은 y 값끼리 더해 Vector 객체의 x 값..

    [Kotlin] MutableMap 사용 시 java.util.ConcurrentModificationException 문제 해결법

    문제 원인 Kotlin에서 mutableMapOf 함수를 통해 생성되는 MutableMap 객체는 내부적으로 Java의 LinkedHashMap을 사용한다. 이 LinkedHashMap은 내부에서 LinkedHashIterator이란 것을 사용하는데, 이 객체는 원소를 순환할 때 LinkedHashMap이 실제로 조작된 횟수(modCount)와 순환이 시작될 때 확인된 조작된 횟수(expectedModCount)의 값을 비교해 만약 두 값이 일치하지 않으면 ConcurrentModificationException을 발생시킨다. abstract class LinkedHashIterator { ... int expectedModCount; ... final LinkedHashMap.Entry nextNode..