코틀린 문법을 공부하다가 배열이 좀 헷갈리는 것 같아서 정리하려 한다. 🧐
코틀린의 배열은 Array 클래스로 표현한다.
public class Array<T> {
public inline constructor(size: Int, init: (Int) -> T)
public operator fun get(index: Int): T
public operator fun set(index: Int, value: T): Unit
public operator fun iterator(): Iterator<T>
}
코틀린에서 Array 클래스는 내부적으로 이렇게 구현되있는 것을 볼 수 있다.
이때, 코드를 보면 Array는 set()
으로 값을 변경할 순 있지만, 새로운 값을 넣거나, 혹은 삭제하는 함수는 없는 것으로 보인다. 다만 get()
을 이용하여 인덱스를 인자로 주어 값을 얻을 순 있는 것으로 보인다.
val ary: Array<Int> = Array(3, {1})
println("바꾸기 전 값: ${ary.get(2)} ")
ary.set(2, 5)
println("바꾼 값: ${ary.get(2)}")
// 바꾸기 전 값: 1
// 바꾼 값: 5
위 코드를 작성해보면 3
개의 인덱스를 가진 Int형 Array
를 생성하여 그 값을 1
로 주었고, set()
과 get()
을 사용하여 값을 바꾸고 그 결과를 확인한 것을 알 수 있다.
Array
는 생성한 순간, 사이즈는 고정되며 원소 삭제나 추가 등을 할 수 없다.set()
과 get()
함수를 이용해도 되지만 대괄호[]
를 이용해서 배열의 데이터에 접근 가능arrayOf
키워드를 통해 선언할 수 있음 (출력 시 java.util.Arrays.toString()
사용)java.util.Arrays.toString()
을 사용하지 않고 그대로 출력 시 주소값이 출력됨val ary = intArrayOf(10, 20, 30)
println(ary)
// [I@7c30a502
Mutable
동작을 한다. 따라서 val
으로 선언하나 var
으로 선언하나 똑같은 동작을 한다.val ary = intArrayOf(10, 20, 30)
ary[2] = 4
println(java.util.Arrays.toString(ary))
// [10, 20, 4]
val
로 선언한 ary3
에 ary2
를 저장하려고 하면 오류가 발생한다.// var 로 선언
var ary2 = intArrayOf(1, 2, 3)
ary2[0] = 4
println(java.util.Arrays.toString(ary2))
// val로 선언
val ary3 = intArrayOf(4, 5, 6, 7, 8) // var로 선언하면 오류 발생하지 않음.
ary3 = ary2
println(java.util.Arrays.toString(ary3))
// Val cannot be reassigned
val c = arrayOf("Stirng", 1)
Array
를 합칠 수 있다.val a = intArrayOf(1, 2, 4)
val b = intArrayOf(9, 3, 7)
val sumab = a + b
println(java.util.Arrays.toString(sumab))
// [1, 2, 4, 9, 3, 7]
Array<Int>
와 intArrayOf()
의 차이점-> 위 코드의 배열을 합치려고 하는 과정에서 한 가지 의문이 발생했었다. intArrayOf()
로 생성한 것과 Array<Int>
는 똑같은 타입이니까 더하는 것이 되겠지 싶었다. 하지만, 더하는 과정에서 서로 타입이 맞지 않아 더하는 것이 되지 않는 오류가 발생했다.
val ary4 = intArrayOf(4, 5, 6, 7, 8)
val ary5: Array<Int> = arrayOf(4, 0, 5)
val sumAry = ary4 + ary5 // 오류 발생
println(java.util.Arrays.toString(sumAry))
그 이유는 Array<T>
는 참조형 자료형(객체)를 데이터의 요소로 가지고, IntArray
와 같은 기본 참조형 array는 기본형을 데이터의 요소로 가지기 때문이다.
즉, IntArray
와 같은 array
타입은 Primitive type이고, 이걸 사용하면 Boxing Overhead 를 피할 수 있다.
또한 Array 클래스와 상속관계는 없지만, 메소드나 프로퍼티는 동일하다고 코틀린 공식 문서에서도 나와있다.
조금 어렵다면, 자바의 박싱, 언박싱 개념을 알면 Array<Int>
는 자바의 Integer[]
와 매핑되고, IntArray
는 자바의 int[]
에 매핑되기 때문에 Overhead
방지를 위해 꼭 구분지어 사용해야 한다는 것을 알 수 있다.
TMI 🤔
오늘 처음으로 공식문서를 읽기도 하고 안드로이드 스튜디오 내부적으로 구현된 파일도 읽다보니 도움이 많이 되는 것 같다.
그리고 박싱 오버헤드 없이 쓸 수 있다는 건 시간복잡도를 생각해야하는 코테에서도 유용하다고 생각되기 때문에 나중에 비교하려고 한다!
Reference📚
참고자료:
https://kotlinlang.org/docs/arrays.html
https://velog.io/@haero_kim/List-%EB%9E%91-Array-..-%EB%8C%80%EC%B2%B4-%EB%AC%B4%EC%8A%A8-%EC%B0%A8%EC%9D%B4%EC%95%BC#%EC%A0%95%EC%A0%81-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%83%80%EC%9E%85-array