!! 개념Kotlin의 !! 문법은 non-null 단언 연산자라고 부르며, 이 표현은 이 값은 절대로 null이 아님을 내가 확신한다고 컴파일러에 말해주는 용도, 만약 그 값이 실제로 null이면, 런타임에 NullPointerException이 발생
!!와 ? 차이점!! : Not-null assertion operatorNullPointerException(NPE) 발생val str: String? = null
val len = str!!.length *// NPE 발생*
? : Safe call operatorval str: String? = null
val len = str?.length *// 결과: null*
let str: String? = nil
let length = str!.count // 런타임 크래시 발생
let str: string | null = null
let length = str!.length; // 컴파일러에 non-null임을 단언
string? s = null;
int len = s!.Length; // Non-null 단언 연산자 (!)
!!를 쓰면 안 되는 이유!!를 쓰면 런타임에 예기치 않은 NPE로 앱이 즉시 크래시!!는 Kotlin의 null safety 기능을 포기하는 것이며, 예외 발생 시 어디서 왜 발생했는지 파하기 어렵다.
!!의 관계Kotlin 컴파일러가 타입 체크 후, 안전하다고 판단되면 자동으로 타입을 변환해줌
fun printLength(obj: Any?) {
if (obj is String) {
println(obj.length) *// obj는 String으로 smart cast*
}
}
별도의 캐스팅 연산자 없이도 안전하게 타입 변환
!!를 써야 하는 경우!!로 강제 변환 필요할 수 있음let으로 대체하는 것이 좋은 이유let은 scope function으로, safe call(?.)과 함께 쓰면 객체가 null이 아닐 때만 블록 실행val str: String? = ...
str?.let { println(it.length) }
Q: 정말로 null이 올 수 없는 상황이면 !! 써도 되나요?
A: 컴파일러가 보장하지 못하는 상황에서만, 그리고 정말 100% 확신할 때만.
하지만 대개 더 안전한 구조로 리팩터링하는 것이 권장됨
*// Bad: NPE 위험*
val name: String? = null
val length = name!!.length *// NPE
// Good: let + safe call*
name?.let { println(it.length) } *// 아무 일도 일어나지 않음, 안전*
!!는 정말 불가피한 상황이 아니면 절대 사용하지 않는다.?.let { ... } 패턴을 적극 활용한다.!!가 보이면 반드시 이유를 확인한다.!!는 Kotlin의 null safety를 무력화하므로 사용을 최대한 지양한다.