🛡️ Null 안전성
📖 Null 안전성이란?
**Null 안전성(Null Safety)**은 NullPointerException을 컴파일 시점에 방지하는 Kotlin의 핵심 기능입니다.
💡 Nullable 타입
Non-null vs Nullable
fun main() {
// Non-null (기본)
var name: String = "홍길동"
// name = null // ❌ 오류!
// Nullable (? 추가)
var nullableName: String? = "홍길동"
nullableName = null // ✅ 가능
}
Nullable 타입 비교
fun main() {
val name: String = "홍길동" // Non-null
val age: Int = 25 // Non-null
val email: String? = null // Nullable
val phone: Int? = null // Nullable
println(name.length) // ✅
// println(email.length) // ❌ 오류!
}
🔧 안전한 호출
?. 연산자
fun main() {
val name: String? = null
// 안전한 호출
val length = name?.length
println(length) // null
val upper = name?.uppercase()
println(upper) // null
}
체이닝
data class Address(val city: String?)
data class Person(val address: Address?)
fun main() {
val person: Person? = Person(Address("서울"))
// 안전한 체이닝
val city = person?.address?.city
println(city) // 서울
val nobody: Person? = null
val noCity = nobody?.address?.city
println(noCity) // null
}
🎯 엘비스 연산자
?: 기본값
fun main() {
val name: String? = null
// null이면 기본값 사용
val displayName = name ?: "이름 없음"
println(displayName) // 이름 없음
val validName: String? = "홍길동"
val display = validName ?: "이름 없음"
println(display) // 홍길동
}
early return
fun processUser(name: String?) {
val validName = name ?: run {
println("이름이 없습니다")
return
}
println("처리: $validName")
}
fun main() {
processUser("홍길동") // 처리: 홍길동
processUser(null) // 이름이 없습니다
}
🔍 !! 연산자
강제 언래핑
fun main() {
val name: String? = "홍길동"
// null이 아님을 확신할 때 (주의!)
val length = name!!.length
println(length) // 3
val nullName: String? = null
// val error = nullName!!.length // ❌ NPE 발생!
}
언제 사용?
// ❌ 나쁜 사용
fun bad(name: String?) {
println(name!!.length) // 위험!
}
// ✅ 좋은 사용 (확실한 경우만)
fun good(name: String?) {
if (name != null) {
println(name.length) // 안전
}
}
🎨 let 함수
null이 아닐 때만 실행
fun main() {
val name: String? = "홍길동"
name?.let {
println("이름: $it")
println("길이: ${it.length}")
}
// 이름: 홍길동
// 길이: 3
val nullName: String? = null
nullName?.let {
println("실행 안 됨")
}
}
체이닝
fun main() {
val name: String? = "홍길동"
val result = name
?.uppercase()
?.let { "안녕하세요, ${it}님!" }
?: "이름 없음"
println(result) // 안녕하세요, 홍길동님!
}