HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
📝
남득윤 학습 저장소
/
Kotlin docs
Kotlin docs
/
▶️
Type checks and casts
▶️

Type checks and casts

 

is 와 !is 연산자

 
is 는 자바의 instanctof 이고 !is 는 instanceof 하고 negation 한 것과 같다.
분기문에 적용하면 Smart casts 가 적용되어 대상 타입으로 캐스팅된다.

Smart casts

  • 코틀린에서는 대부분의 경우 명시적인 casting 연산을 해줘야 하는 경우가 없습니다.
  • 기본
 
  • negation 후 return 한 경우
 
  • && 혹은 || 의 오른쪽에서
 
  • when 절, while 절 에서도!
 
  • 짱짱 컴파일러가 캐스팅 하려는 순간마다 알아서 해줄 것입니다.
 
구체적으로는 val/val, 지역변수/property 에 따라 다른 전략을 사용합니다.
이는 나중에 공부합시다!
 

“Unsafe” cast operation

 
보통, 캐스팅은 캐스팅이 불가능 할 때 예외를 터트립니다. 그래서 그냥 “Unsafe”라고 부르기로 했습니다.
unsafe casting 은 중위 연산자 as 로 합니다.
 

“Safe” (nullable) cast operator
예외를 막을려면 safe 한 캐스팅 연산자 as? 를 활용하면 됩니다. as? 는 캐스팅을 못 할때 null을 반환합니다.
 

타입 이레이저와 제네릭 타입 체크

 
코틀린은 제네릭의 타입 정보를 컴파일 타임에 지워버린다 (type erasure)
그래서 런타임에 제네릭 타입의 instance 는 실제 type argument 에 대한 정보를 전혀 들고 있지 않다.
 
예를 들어 List<Foo> 는 타입 이레이저를 통해 그냥 List<*> 이다.
일반적으로 런타임에 이를 확인할 방법은 없다 (아마 super type token 쓰면 될듯?)
 
때문에 컴파일러는 is 를 제네릭에 사용하는 방식을 제한한다.
e.g. ) ints is List<Int>or list is T(type parameter)
 
하지만 star-projected type 을 사용할 수 있다!
inline functions with reified type parameters
나중에 공부하자
 

Unchecked casts

나중에 공부하자
fun demo(x: Any) { if (x is String) { print(x.length) // x is automatically cast to String } }
if (x !is String) return print(x.length) // x is automatically cast to String
// x is automatically cast to String on the right-hand side of `||` if (x !is String || x.length == 0) return // x is automatically cast to String on the right-hand side of `&&` if (x is String && x.length > 0) { print(x.length) // x is automatically cast to String }
when (x) { is Int -> print(x + 1) is String -> print(x.length + 1) is IntArray -> print(x.sum()) }
val x: String = y as String
val x: String? = y as String?
val x: String? = y as? String
if (something is List<*>) { something.forEach { println(it) } // The items are typed as `Any?` }
inline fun <reified A, reified B> Pair<*, *>.asPairOf(): Pair<A, B>? { if (first !is A || second !is B) return null return first as A to second as B } val somePair: Pair<Any?, Any?> = "items" to listOf(1, 2, 3) val stringToSomething = somePair.asPairOf<String, Any>() val stringToInt = somePair.asPairOf<String, Int>() val stringToList = somePair.asPairOf<String, List<*>>() val stringToStringList = somePair.asPairOf<String, List<String>>() // Compiles but breaks type safety! // Expand the sample for more details fun main() { println("stringToSomething = " + stringToSomething) println("stringToInt = " + stringToInt) println("stringToList = " + stringToList) println("stringToStringList = " + stringToStringList) //println(stringToStringList?.second?.forEach() {it.length}) // This will throw ClassCastException as list items are not String }