스타 프로젝션(List<*>) 예제
fun printList(list: MutableList<*>) {
// 리스트의 요소를 안전하게 읽을 수 있다. 하지만 쓰기는 불가능하다. (반환 타입은 Any?로 추론)
for (item in list) {
println(item)
}
}
fun main() {
val stringList: MutableList<String> = mutableListOf("A", "B", "C")
printList(stringList)
val intList: MutableList<Int> = mutableListOf(1, 2, 3)
printList(intList)
}
MutableList<*>는 "모든 타입의 리스트"를 받겠다는 의미지만, 구체적인 타입 정보가 없으므로 읽기 전용이다.
List<Any> 사용 예제
fun addElement(list: MutableList<Any>, element: Any) {
// MutableList<Any>는 어떤 타입의 값도 추가 가능.
list.add(element)
}
fun main() {
val anyList: MutableList<Any> = mutableListOf(1, "문자열")
addElement(anyList, 3.14)
println(anyList
// 하지만 MutableList<String>은 MutableList<Any>의 하위 타입이 아님.
val stringList: MutableList<String> = mutableListOf("A", "B")
// addElement(stringList, "C") // 컴파일 에러!
}
여기서 addElement 함수는 MutableList<Any>를 인자로 받으므로, 리스트에 어떤 타입의 값도 추가할 수 있다. 그러나 제네릭은 불공변하기 때문에, MutableList<String>은 MutableList<Any>의 하위 타입이 아니어서 호출할 수 없다.
정리하자면, MutableList<Any>는 명시적으로 Any를 사용하여 모든 타입의 값을 추가할 수 있지만, MutableList<*>는 타입 인자가 불명확해 읽기 전용으로만 안전하게 사용할 수 있다.
String은 Any의 하위 타입이다. 하지만, 제네릭 타입인 MutableList<String>은 불공변성(invariance) 때문에 MutableList<Any>의 하위 타입이 아니며, 이는 Int가 Number의 하위 타입임에도 불구하고 MutableList<Int>가 MutableList<Number>의 하위 타입이 아닌 것과 동일한 원리다.
반응형
'Kotlin' 카테고리의 다른 글
[Kotlin in Action] 10.2 리플렉션: 실행 시점에 코틀린 객체 내부 관찰 (0) | 2025.04.03 |
---|---|
[Kotlin in Action] 10.1 annotation 선언과 적용 (0) | 2025.04.03 |
[Kotlin] 코틀린 선언 지점 변성과 자바 와일드카드 비교 (0) | 2025.04.03 |
[Kotlin in Action] 9.3 변성: 제네릭과 하위 타입 (0) | 2025.04.02 |
[Kotlin in Action] 9.2 실행 시 제네릭스의 동작: 소거된 타입 파라미터와 실체화된 타입 파라미터 (0) | 2025.04.02 |
댓글