[Android/Kotlin] [TIL] 지연초기화, 널 세이프티
지연초기화와 널 세이프티에 대해서 알아보자
01. 지연초기화
지연초기화란 변수나 상수값을 나중에 초기화 할 수 있는 것이다.
- 코틀린은 클래스를 설계할 때 안정성을 위해 반드시 변수의 값을 초기화할것을 권장한다.
- 이 때 클래스를 설계할 때 초기의 값을 나중에 대입하기 위한 문법이다.
Kotlin의 지연초기화
lateinit
: 변수를 지연 초기화 하기 위해 사용
lazy
: 상수를 지연 초기화 하기위해 사용
지연초기화의 장점
- 저사향으로 제한되어있는 환경에서 메모리를 효율적으로 사용 가능하다.
예시코드
변수의 지연초기화
fun main(){ var s1 = Student() s1.name = "참새" s1.displayInfo() s1.age = 10 s1.displayInfo() } class Student { lateinit var name:String //name값을 지연초기화 하기위해 lateinit 사용 var age:Int = 0 fun displayInfo() { println("이름은: ${name} 입니다.") println("나이는: ${age} 입니다.") } }
고급사용
fun main(){ var s1 = Student() s1.name = "참새" s1.displayInfo() s1.age = 10 s1.displayInfo() } class Student { lateinit var name:String var age:Int = 0 fun displayInfo() { if(this::name.isInitialized) { //값이 초기화 되어있는지 확인 println("이름은: ${name} 입니다.") println("나이는: ${age} 입니다.") } else { println("name변수를 초기화해주세요.") } } }
상수의 지연초기화
fun main(){ var s1 = Student() s1.name = "참새" s1.displayInfo() s1.age = 10 s1.displayInfo() } class Student { lateinit var name:String var age:Int = 0 val address: String by lazy { println("address 초기화") "seoul" } fun displayInfo() { println("이름은: ${name} 입니다.") println("나이는: ${age} 입니다.") println("주소는: ${address} 입니다.") } }
02. 널 세이프티
- Kotlin의 Null 안정성을 향상시켜준다.
- Null 예외는 프로그램의 가용성을 저하시키는 오류이다.
- Kotlin은 안전한 설계를 위해 자료형에 Null 여부를 명시할 수 있다.
Null Safety방법
- Null 예외로부터 안전한 설계를 위한 다양한 키워드들을 지원한다.
- Null 예외를 피하기 위해 Kotlin에서는
?
,!!
,?.
,?:
등을 사용한다. - 여기서
!!
는 강제로 Null값이 아니라고 설정해주는 것이므로 최대한 사용을 지양하자
예시코드
1. address변수를 null값 저장이 가능하도록 String?
으로 선언한다.
fun main(){
var s = Student()
s.name = "참새"
s.address = "서울"
s.displayInfo()
}
class Student {
lateinit var name:String
var address:String? = null // Null Safety! [?]
fun displayInfo() {
println("이름은: ${name} 입니다")
println("주소는: ${address} 입니다")
}
}
2. 메소드를 호출한 후 리턴값이 null이 아니라고 !!
로 보증한다.
fun main(){
// var data = readLine()!!.toInt()
var inputData = readLine()!! // Null Safety! [!!]
var data = inputData.toInt()
println("Null아닌 값: ${data}")
}
3. Null인지 확인하고 Null이 아닐때만 참조하는 메소드를 실행하기위해 ?.
사용
주소값을 갖는 address는 초기값이 null로 설정되어 있기 때문에 Null 위협에 놓여있다.
- Null이 아님을 보장할 때 강제로
!!
를 사용하는 것은 옳지 않다. - 그래서 안전호출 연산자(safe-calls)인
?.
을 사용한다.!
fun main(){
var s = Student()
s.name = "참새"
s.displayAddressLength()
s.address = "서울"
s.displayInfo()
}
class Student {
lateinit var name:String
var address:String? = null
fun displayInfo() {
println("이름은: ${name} 입니다")
println("주소는: ${address} 입니다")
}
fun displayAddressLength() {
println("주소의 길이는: ${address?.length} 입니다")// safe calls 사용! [?.]
}
}
4. ?.
키워드로 안전하게 실행한 후 null이 출력되는것을 막고싶다면?
?:
키워드를 사용해 null 대신에 다른 문자열을 출력하도록 가능하다.?:
를 엘비스 연산자 라고한다.
fun main(){
var s = Student()
s.name = "참새"
s.displayAddressLength()
s.address = "서울"
s.displayInfo()
}
class Student {
lateinit var name:String
var address:String? = null
fun displayInfo() {
println("이름은: ${name} 입니다")
println("주소는: ${address} 입니다")
}
fun displayAddressLength() {
println("주소의 길이는: ${address?.length ?: "초기화하세요"} 입니다") //엘비스 연산자 함께 사용! [?:]
}
}