231222 TIL #275 Kotlin #10 원시 타입 / 컬렉션과 배열

김춘복·2023년 12월 22일
0

TIL : Today I Learned

목록 보기
275/571

Today I Learned

Kotlin in Action 이어서 공부..


코틀린의 원시 타입

자바에선 원시타입과 참조타입을 구분한다.
하지만 코틀린은 원시타입과 래퍼타입을 구분하지 않고 항상 같은 타입을 사용한다.

  • 코틀린에서 원시 타입(ex. Int)은 가능한 가장 효율적인 방식으로 표현된다.
    대부분의 경우 자바의 원시타입처럼 컴파일 되며 컬렉션 같은 제네릭 클래스를 사용할땐 래퍼타입으로 작동된다.

  • 자바에선 참조타입만 null이 가능하다.
    Int?, Boolean? 같은 nullable한 원시 타입을 사용하면 자바의 래퍼타입으로 컴파일 된다.

  • 최상위 타입 Any, Any?
    자바의 object와 비슷한 최상위 타입이다.
    object는 참조타입만 정점이지만, Any는 원시와 참조 모든 타입에서 최상위 타입이다.

  • Unit
    자바의 void와 같은 기능을 한다.
    Unit을 굳이 안쓰고 반환 타입을 아무것도 안써도 void 처럼 동작한다.
    하지만 void는 아무것도 반환하지 않는 것이고, Unit은 Unit을 묵시적으로 반환하기에 차이가 있긴 있다.(물론 Unit엔 Unit만 있고 아무것도 없다. 사실상 void)

fun f() : Unit {...}
fun f() {...}
  • Nothing
    함수가 항상 예외를 던지거나 무한 루프에 빠져 반환하지 않는 등의 상황에서 사용된다.
    Nothing 타입은 아무 값도 포함하지 않는다.
    함수의 반환 타입이나 타입 파라미터로만 쓸 수있고 변수 저장같은 타입으로는 쓸 수 없다.
    모든 타입의 하위 타입으로 취급되어 모든 타입과 호환된다.
fun throwError(message: String): Nothing {
    throw IllegalArgumentException(message)
}

숫자 변환

코틀린은 한 타입 숫자를 다른 타입 숫자로 자동변환 하지 않는다.

  • 따라서 toByte(), toLong(), toChar() 같은 원시 타입 변환 함수를 사용해 직접 바꿔야 한다.

  • 다만, + - * / 같은 산술 연산자는 별도 변환 없어도 적당한 타입의 값을 받아 들이게 이미 오버로드가 되어있다.


컬렉션과 배열

Nullable 컬렉션

  • 컬렉션의 타입 인자 뒤에 ?를 붙이면 컬렉션에 null을 넣을 수 있다는 뜻이다.
val list = ArrayList<Int?>() // 리스트의 원소가 Int거나 null
val list2 = ArrayList<Int>?() // 리스트 자체가 있거나 null

list.filterNotNull() // null 값을 걸러내주는 함수(코틀린 표준 라이브러리)

읽기 전용 & 변경 가능 컬렉션

또 다른 코틀린 컬렉션의 차별점은 컬렉션 안의 데이터에 접근하는 인터페이스(Collection)와 데이터를 변경하는 인터페이스(MutableCollection)를 분리했다는 점이다.

  • 읽기전용 컬렉션 : kotlin.collections.Collection
    ex) size, iterator(), contains()

  • 변경 가능 컬렉션 : kotlin.collections.MutableCollection
    ex) add(), remove(), clear()

  • 어떤 함수에서 인자를 Collection으로 받는지, MutableCollection으로 받는지에 따라 그 함수에서 컬렉션을 읽기만 할지, 데이터를 변경할지 알 수 있다.

  • 한 컬렉션 객체에서 참조를 읽기전용, 변경가능 2가지로 할 수 있다는 것이다.
    그래서 꼭 읽기전용이 항상 thread-safe 하다거나 하진 않다.


배열

코틀린 배열은 타입 파라미터를 받는 클래스다. 배열의 원소 타입은 타입 파라미터에 의해 결정된다.

  • 코틀린의 배열(Array 클래스)은 일반 제네릭 클래스처럼 보이지만, 자바 배열로 컴파일 된다.

  • 원시 타입의 배열은 IntArray와 같이 각 타입에 대한 특별한 배열로 표현된다.

  • 배열 생성 방법

    val arr1 = arrayOf(1,3,4,6,7)	// arrayOf(elements)로 원소 직접 넘기기
    val arr2 = arrayOfNulls<Int>(5) // arrayOfNulls<타입>(원소개수)로 null이 든 배열 만들기
    val arr3 = Array<Int>(5){ p -> i+1 } // Array<타입>(원소개수){ 람다식 }
  • toTypedArray() : 컬렉션 -> 배열 변환 메서드

순회용 함수

  1. indices()

    컬렉션 타입의 인덱스 값을 의미.

fun main() {
	var data = arrayOf<Int>(5, 10, 15, 20)
    for (i in data.indices) {
    	print(data[i])
        if (i != data.size-1) print(", ")
    }
}// 출력 5, 10, 15, 20
  1. withIndex()

    인덱스와 실제 데이터를 함께 가져오는 함수

fun main() {
	var data = arrayOf<Int>(10, 20, 30, 40)
    for ((index, value) in data.withIndex()) {
    	print(value)
        if (i != data.size-1) print(", ")
    }
}// 출력 10, 20, 30, 40
profile
Backend Dev / Data Engineer

0개의 댓글