-
[Kotlin] Type check and Type castsKotlin/Types 2021. 8. 13. 19:02
kotlin은 nullable변수가 존재해서 간단한 연산자조차도 어렵게 느껴진다......
is와 as연산자를 살펴보고 ?가 붙어있을 때는 어떻게 동작하는지에 대해서 알아보자.
다음과 같이 사용할 수 있다.
x is String?
x is String
x as String
x as? String
x as? String?
코틀린에서는 nullable한 변수가 존재하기 때문에 연산자를 사용할 때도 상황에 따라 ?를 붙여줘야 한다.
is and !is operator - 타입 체크 연산자
변수에 담겨있는 인스턴스가
비교하는 클래스와 같은범위, 넓은범위이면 true
비교하는 인터페이스를 구현하였으면 true
자바의 instanceof연산자와 같다.
밑의 테스트1, 테스트2, 테스트3는
x is 클래스? 에 대한 동작이다.
쓸모때가리가 거의 없는데 그냥 넣어놨다.
안 보고 다음내용으로 넘어가도 좋다.
x is 클래스? 의 true, false 동작
x is 클래스 or x가 null 과 같다.
테스트1
null이 담길 수 없는 non-null변수에는 is 연산자뒤에 비교할 타입에 ?가 있으나 없으나 차이가 없다.
테스트2
nullable한 변수로 선언했지만 변수에 null이 들어있지 않아서 결과는 테스트1과 완전히 똑같다.
is 연산자는 어떠한 변수로 선언되었는지와 관계없이 초기화되어있는 값과 관련하여 동작한다라는 것을 알 수 있다.
테스트3
println(parent is Parent)
println(parent is Child)
println(child is child)
println(child is parent) 들이 모두 false인 것은 위의 자바의 동작과 비슷해서 이해할 수 있다.
나머지 네개인 ?가 달린 is 연산자를 보면 테스트1과 차이를 보인다.
변수가 Parent, Child인스턴스가 아님에도 변수에 null이 담겨있어 true로 리턴됨을 확인했다.
parent is Parent?는 null || Parent인스턴스 조건이면 true
parent가 Parent인스턴스여도 true , null이여도 true가 된다.
as, as? - 타입 캐스트 연산자
as는 다른 타입으로 캐스팅하는 연산자이다.
변수 as 캐스팅타입
변수가 캐스팅타입으로 변하게 된다.
safe cast - as?
as를 사용할때 캐스팅이 불가한 경우에 예외가 발생하는데
as에 ?를 달아 as?로 safe cast를 사용하면 casting이 불가능한 경우 casting은 되지 않고
예외발생 대신 null을 리턴한다.
fun main() { val tString: String = "kotlin" val tInt: Int = tString as Int //Runtime에서 ClassCastException발생 val tString2: String = "kotlin" val tInt2: Int = tString2 as? Int //컴파일 에러- smart cast as?의 리턴형은 Int? //Int?형 tInt2선언해야함 val tString3: String = "kotlin" val tInt3: Int? = tString3 as? Int //ok val tInt4 = tString3 as? Int //ok // inferred type(암시적 타입 추론) 으로 tInt4는 Int?형으로 된다. }
(추가)
safe cast를 사용시 캐스팅에 실패하였다면 단지Int?형인 null을 리턴하는데
그 값을 다른 임시 변수에 담을 수 있는 것이다.
tString3가 Int?형으로 캐스팅되고 null을 가지는 것이 아니다.
(참고)
var x:String= 6.toString() var y:Int= "7".toInt()
6.toString()은 String형 casting이 아니라 String을 만들어주는 function이다.
"7".toInt()마찬가지로 Int형 casting이 아니라 Int를 만들어주는 function이다.
Smart casts
is로 타입체크를 하면
컴파일러가 타입체크가 된 확실한 구간에서 as연산자로 명시적 형변환할 필요없이
형변환된 타입으로 바로 사용할 수 있게 해준다.
불필요한 코드
x의 타입이 String인지 is연산자로 타입체크 후
타입이 맞으면 String타입으로 명시적으로 형변환을 한다.
컴파일러가 자동으로 캐스팅해주기 때문에 형변환이 필요없이 다음과 같이 사용하면된다.
when expression, while loop에도 smart casting을 사용할 수 있다고 한다.
as, as?, smart casting도 봤으니 is 연산자의 동작을 한번 더보자.
unsafe type cast
as연산자는 unsafe한 cast연산자이다.
casting이 불가능하면 ClassCastException이 발생하고
null이 담겨있으면 NullPointerException이 발생한다.
val x: String = y as String
만약 y가 nullable변수이고 null이 담겨있었다면 어떨까?
y에 null이 담겨있을 경우 ClassCastException대신 NullPointerException이 발생한다.
(null as String) -> NPE발생
그렇기 때문에 다음과 같이 바뀌어야만한다고 써있다.
val x: String? = y as String?
다음의 safe cast연산자와 뭔 차이가 있지????하고 테스트를 몇번해보니 본질의 차이를 이해할듯 말듯한다...
val x: String? = y as? String
y as String?의 의도는 NPE방지에 있고
y as? String의 의도는 ClassCastException방지에 있는 것 같다.
Type erasure and generic type checks
https://kotlinlang.org/docs/typecasts.html#type-erasure-and-generic-type-checks
Unchecked casts
https://kotlinlang.org/docs/typecasts.html#unchecked-casts
'Kotlin > Types' 카테고리의 다른 글
[Kotlin] Array (0) 2021.12.16 [Kotlin] Nothing, Unit (0) 2021.08.16 [Kotlin] 코틀린 패키지 / .kt파일과 .java파일 (feat. top-level선언) (0) 2021.07.21 [Kotlin] val / const val (0) 2021.07.21 [Kotlin] 변수/자료형 (0) 2021.07.07