Kotlin

코틀린이 제공하는 자료형

재심 2024. 10. 5. 11:44

목차

    코틀린은 원시 타입은 제공하지 않고 모든 자료형을 참조형으로 제공한다고 한다.

     

    코틀린의 자료형 속도는?

    원시형은 성능적으로 참조형보다 유리하다. 하지만 코틀린은 원시형을 제공하지 않는다. 그렇다면 코틀린은 자바에 비해 느릴 수 밖에 없지 않을까?

     

    하지만 코틀린에서 자료형을 아래처럼 저장하면 실제 내부적으로는 자바의 원시형 int를 사용한다고 한다.

    Long, Byte도 동일하게 자바의 원시형 타입을 사용한다.

    a: Int = 4
    
    java.lang.Class<kotlin.Int> = int

     

    단지 원시형을 한 번 감싼 형태로 제공하고 있으며 실제 성능적으로도 자바 원시형과 동일한 속도를 낸다고 한다.

    바이트 코드로 변환 후에도 확인해보면 자바의 원시형을 사용했을 때와 동일하게 컴파일 된다고 한다.

     

    결론적으로 코틀린은 참조 자료형만 제공하지만 실제 컴파일 할 때는 자바의 원시형과 동일한 바이트 코드를 사용해서 최적화를 지원하기 때문에 성능적으로 손해볼일은 없다고 생각하면 된다.

     

    그렇다면 어떻게 원시형을 제공하면서 참조형의 편의기능을 제공할까?

    예를 들어, 아래와 같은 코드가 있다고 가정하자.

    val a = intArrayOf(1, 4, 3)
    println(a.max())

     

    배열의 최대 값을 구하는 코드인데, max기능은 디스어셈블리어로 살펴보면 내부적으로 Method/kotlin/collections/ArraysKt.max() 메서드를 호출하는 방식으로 제공한다.

     

    즉, 참조형 같았지만 원시형을 사용하면서 내부적으로 다른 패키지를 호출해서 편의기능을 제공하고 있는 방식인 것이다.

     

    코틀린의 컬렉션 프레임워크

    코틀린에서 컬렉션 프레임워크는 인터페이스만 코틀린에서 만들고 실제 자료형은 자바의 컬렉션 프레임워크를 활용한다고 한다.

    예를 들어, 리스트의 경우 인터페이스는 kotlin.collections.List를 쓰지만 실제 구현은 java.util.ArrayList를 사용한다.

     

    범용적인 자바 표준을 사용해서 호환성을 높이고 상호운용성을 위해 코틀린이 이 같은 방식을 택했다고 한다.

    또한 코틀린에서는 자바가 지원하지 않는 더 많은 기능을 제공하기도 한다.

     

    리스트의 최대 값을 구할 때 자바에서는 아래처럼 사용한다.

    List<Integer> list = new ArrayList<>();
    list.add(1);
    list.add(2);
    list.add(3);
    
    // Collections의 기능 활용
    Collections.max(list1)

     

    하지만 코틀린에서는 바로 구할 수 있도록 지원한다.

    val list = arrayListOf(1, 2, 3)
    list.max()

     

    이러한 기능을 제공할 수 있는 이유는 코틀린에서 제공하는 확장 함수와 연관이 있다.

     

    확장 함수

    코틀린은 자바와의 상호 운용성을 중시해서 자바의 클래스를 그대로 활용은 하지만 좀 더 개선해서 활용하고 싶었다고 한다. 이를 위한 방법이 확장 함수라고 한다.

     

    원래 자바에서는 클래스에 메소드를 추가하려면 클래스 내부에서 코드를 수정해야 했다. 하지만 코틀린에서는 확장함수를 통해 이를 구현한다.

     

    리스트의 마지막 원소를 구하고 싶은 경우가 있는데 자바에서는 기본적으로 제공하지 않는다. 구현하려면 클래스 내부를 수정해야 한다. 하지만 코틀린에서는 lastElement 라는 확장함수를 추가해 이를 구현한 것을 볼 수 있다.

    var list = listOf(1, 2, 3)
    
    // 마지막 element를 가져오는 확장 함수
    fun List<Int>.lastElement(): Int = this.get(this.size - 1)

     

    코틀린이 별도로 구현한 컬렉션 인터페이스

    코틀린은 기본적으로 자바 컬렉션 프레임워크를 사용한다. 하지만 코틀린이 추가적으로 구현한 컬렉션들도 있다.

    바로 Mutable 타입들인데 코틀린은 불변/가변을 매우 엄격히 따진다.

     

    그래서 List, Set, Map은 불변이며 만약 값을 수정해야 하는 경우 MutableList, MutableSet 과 같은 자료형을 사용해야 한다.

    그래서 List의 경우 코틀린의 Collection 인터페이스를 상속받으나 생성/조회 함수만 있으며 MutableCollection을 상속받은 MutableList를 사용해야 수정/삭제를 할 수 있다.

     

    List

    1. List

    • List<T>는 읽기 전용 리스트를 나타내는 인터페이스입니다. 이는 요소를 조회할 수 있지만, 추가, 삭제, 수정 등의 작업은 허용되지 않습니다.
    • 기본적으로 코틀린의 List는 ArrayList와 같은 자바의 구현체를 기반으로 합니다. 하지만 List는 기본적으로 불변(immutable)으로 설계되어 있어, 한 번 생성된 후에는 요소를 변경할 수 없습니다.

    2. MutableList

    • MutableList<T>는 수정 가능한 리스트를 나타내는 인터페이스입니다. 이는 요소를 추가, 삭제 및 수정할 수 있는 메서드를 제공합니다.
    • MutableList의 기본 구현체는 일반적으로 ArrayList입니다. 그러나 내부 구현에 있어서는 구현체가 꼭 ArrayList일 필요는 없으며, 다른 수정 가능한 리스트 구현체(예: LinkedList)도 사용할 수 있습니다. 하지만 코틀린의 표준 라이브러리에서는 ArrayList를 주로 사용합니다.

     

    생성 함수 코틀린 자료형 자바 클래스 불변 여부 비고
    listOf() List<Int> java.util.Arrays$ArrayList O Arrays$ArrayList는 자바에서도 불변
    mutableListOf() MutableList<Int> java.util.ArrayList X  
    arrayListOf() java.util.ArrayList<Int> java.util.ArrayList X  

     

    이 때 arrayListOf의 경우 직접적으로 java.util.ArrayList를 사용하는 방식이다. 만약 코틀린에서 MutableListOf를 구현할 때 현재의 ArrayList가 아닌 LinkedList를 채택한다고 가정했을 때 arrayListOf를 사용하고 싶다면 arrayListOf를 사용해야 할 것이다.

     

    즉, 현재는 mutalbeListOf가 내부적으로 자바의 ArrayList를 사용하니까 불필요해보이지만 명시적으로 arrayList를 사용하고 싶을 때 사용하면 된다.

     

    그리고 코틀린에서는 아직까지 LinkedList를 직접 제공하지는 않는다. 하지만 필요하다면 자바의 LinkedList를 import해서 그대로 사용하면 된다.

     

    Map

    map의 경우 코틀린에서는 내부적으로 자바의 LinkedHashMap을 사용한다.

    그래서 순서가 보장되는 맵 자료형을 사용한다고 보면 된다.

     

    생성 함수 코틀린 자료형 자바 클래스 불변 여부 비고
    mapOf() Map<String, Int> java.util.LinkedHashMap O  
    mutableMapOf MutableMap<String, Int> java.util.LinkedHashMap X  
    hashMapOf() java.util.HashMap<String, Int> java.util.HashMap X  
    linkedMapOf() java.util.LinkedHashMap<String, Int> java.util.LinkedHashMap X  
    sortedMapOf() java.util.SortedMap<String, Int> java.util.TreeMap X  

     

    또한 map의 경우는 mapOf와 mutableMapOf도 내부적으로 둘다 자바의 LinkedHashMap을 사용한다.

    리스트의 경우 arrayListOf()도 내부적으로는 ArrayList를 사용했지만 map의 hashMapOf는 LinkedHashMap 대신 HashMap을 사용하도록 되어 있다.

     

     

    'Kotlin' 카테고리의 다른 글

    코틀린의 실행 과정  (0) 2024.10.03
    코틀린의 접근 제어  (0) 2024.10.03
    코틀린의 기본 문법 정리  (0) 2024.10.03
    Kotlin 이란  (0) 2024.10.03