Overview
-
Kotlin에서 ImmutableList를 반환하는 listOf( )를 사용하여 재미난 실험을 해보자.
-
listOf( )가 반환하는 인스턴스를 강제로 MutableList로 Type Casting을 하고
그 인스턴스에 값을 추가하는 행위를 해보려고 한다.
Problem
fun test() {
val list = listOf(1, 2, 3)
if (list is MutableList) {
list.add(4)
}
}
fun main() {
test()
}
-
위 코드를 실행시키면 어떻게 될까?
-
컴파일 에러가 발생하진 않고 런타임에 UnsupportedOperationException가 발생한다.
Exception in thread "main" java.lang.UnsupportedOperationException
at java.base/java.util.AbstractList.add(AbstractList.java:153)
at java.base/java.util.AbstractList.add(AbstractList.java:111)
at dev.be.kotlinsandbox.KotlinSandboxApplicationKt.test(KotlinSandboxApplication.kt:9)
at dev.be.kotlinsandbox.KotlinSandboxApplicationKt.main(KotlinSandboxApplication.kt:14)
at dev.be.kotlinsandbox.KotlinSandboxApplicationKt.main(KotlinSandboxApplication.kt)
Deep Dive
1. // java.util.ArrayList.ArrayList()
2. ArrayList list1 = new ArrayList<Integer>();
3. list1.add(1);
4.
5. // java.util.Arrays.asList
6. List<Integer> list2 = Arrays.asList();
7. list2.add(1);
-
Problem에서 왜 UnsupportedOperationException가 발생했는지 파악하기 위해
잠시 Java 코드로 돌아와 위 코드를 살펴보도록 하자.
-
위 코드 또한 7번째 줄에서 UnsupportedOperationException가 발생한다.
-
그 이유는 알아보기 위해 우리는 ArrayList와 Arrays에 대해 학습할 필요가 있다.
ArrayList
java.util.ArrayList#add(E)
/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
-
ArrayList를 살펴보면 Dynamic하게 Size를 조절한다.
( 자세한 설명은 다른 글 혹은 직접 코드를 살펴보는 것을 추천한다. )
Arrays
java.util.Arrays#asList
-
Arrays는 Fixed Size이므로
임의로 값을 추가하려고 하면 UnsupportedOperationException가 발생한다.
Answer
fun test() {
val list = listOf(1, 2, 3) // [1]
if (list is MutableList) { // [2]
list.add(4) // [3]
}
val toMutableList = list.toMutableList() // [4]
toMutableList.add(4)
}
-
[1] : Kotlin에서 listOf( )를 호출하면 ImmutableList인 Arrays.ArrayList 인스턴스를 반환한다.
-
[2] : ImmutableList를 강제로 MutableList로 변환하고
-
[3] : 값을 추가하려고 하면 ImmutableList이므로 Exception이 발생한다.
-
[4] : 그러므로 list 프로퍼티에 값을 추가하려면 MutableList 인스턴스를 새로 생성하여야 한다.
-
Type of list property : Arrays.ArrayList
-
Type of toMutableList property : ArrayList
Summary
-
Kotlin에서 listOf( )는 ImmutableList를 반환한다.
-
Array.ArrayList vs Arrays.ArrayList 차이에 대해 알아봤다.
아무 생각 없이 사용했던 코드들에 대해 한번쯤을 되돌아볼 수 있는 시간이 되었다.