안녕하세요, 반갑습니다!
개발을 하다보면 값이 없거나 'NullPointerException' 오류 메시지를 만날때가 있습니다.
코드가 짧으면 금방 찾을 수 있지만, 조금 길어지고 참조해야할 변수들이 많아지기 시작하면 휴...
그래서 우리 개발자들은 이 null 값에 대한 처리를 안할 수가 없습니다.
신경안쓰면 프로그램 또는 앱이 멈춰 버리는 일이 발생할 수도 있으니까요.
코틀린은 Null에 대한 처리에 꽤 많은 공을 들인 언어입니다.
늦은 초기화(lateinit, lazy), 안전 호출(?.), 엘비스 연산자(?:) 등에서 확인 할 수가 있죠.
먼저 초기화 및 null 허용을 안해준 코드를 작성하고 실행을 하면,
var todayNum:Int //초기화 없이 변수 선언
//var todayNum:Int = null //오류 발생, null 부분에 빨간줄이 생김
이렇게 초기화를 반드시 해야한다며 오류를...
네, 역시 null 을 허용하지 않습니다.
오늘의 포스팅
null 에 대한 안정적인 처리!
Null 허용성(Null Safety)
물론 위 방법처럼 선언 후 바로 밑에서 초기화를 해주면 문제는 없습니다.
하지만~ Null 허용성(Null Safety)에 대한 포스팅이니까요^^.
방법은 간단합니다. 변수를 선언할 때 자료형 타입뒤에 물음표( ? ) 만 붙여주면 됩니다.
var todayNum:Int? = null //위와 달리 빨간줄이 사라짐
타입 뒤에 물음표(?) 만 붙여주면 null 초기화가 가능합니다.
이제 이렇게 선언된 변수를 사용해 볼까요?
1. 안전 호출 연산자
첫 번째로 안전 호출 연산자( ?. ) 를 사용해서 변수를 사용할 수 있습니다.
이 연산자는 null이 아닌 경우에만 값을 반환 합니다. 만약 null 값이면 null 을 반환하는 것이죠.
이 연산자로 null 체크를 기존의 자바보다 훨씬 간단하게 코드를 작성할 수 있게 됩니다.
기존의 자바였다면,
Long idx = arguments.getLong("IDX")//null을 확인하지 않고 일단 getLong()을 호출함
if (idx != null) {
...
}
이렇게 null 체크를 해야겠죠?
하지만, 코틀린의 이 안전 호출 연산자로 인해서 아래와 같이 간단히 사용할 수 있습니다.
val idx = arguments?.getLong("IDX") //arguments 가 null 이면 getLong() 을 호출하지 않음
즉, 안전 호출 연산자( ?. ) 는 값에 따라 뒤에 나오는 속성 또는 명령어를 처리하기 위해 사용하는 것입니다.
2. 엘비스 연산자
두 번째는 엘비스 연산자( ?: ) 입니다.
안전 호출 연산자( ?. )를 써서 null 이 아닐 때만 호출을 할 수도 있지만, null 대신 기본 값으로 출력할 수도 있습니다.
val idx = arguments?.getLong("IDX") ?: 0 //null 일 경우 null 대신 0 이 됨
print("idx 는 ${idx} 입니다." ) // "idx 는 0 입니다" 로 출력됨
두 방법 외에도 값을 가져올 수 있는 방법이 있습니다.
바로 단언 연산자( !! ) 를 사용해서 값을 보증 하는 것입니다.
var number_1 = 10
var number_2:Int? = null;
var sum = number_1 + number_2!! //단언 연산자(!!) 를 써서 오류가 사라짐
print("합계 $sum")
위 코드에서 단언 연산자( !! ) 를 쓰지 않는다면, 바로 빨간줄이 쫙! 생깁니다.
하지만, 단언 연산자( !! )를 쓰므로써 오류는 사라집니다.
말 그대로 값이 "null 임을 보증할테니 그냥 써!" 라고 하는 것이죠.
뭐.. 그래도 저런 식이면 바로 'NullPointerExceptino' 오류를 바로 만나긴 합니다.
그러므로 이 방법은 가급적 지양해야 하는 방법입니다.
코드 스멜 (code smell) 이라고 잠재적으로 문제가 있는 코드를 말합니다.
위 오류처럼 막상 까보니 null 일 수 있고, 문제가 생길 수 있기 때문이죠.
One more thing!
· 함수에도 null 허용하기
함수의 파라미터와 반환 값 또한 null 허용성(Null Safety) 을 사용할 수 있습니다.
fun getStrLength(str: String?) : Int? {
var result:Int? = str?.length //str이 null이면 length를 호출하지 않음
return result
}
str 이 null 이면 length 를 호출하지 않으니, result 는 null 이 됩니다.
기존 자바에 비해서 무조건 초기화를 해야하는 번거로움이 있긴하지만,
null 에 대한 처리를 변수 선언단계부터 하기 때문에 안정성은 더 높아졌다고 할 수 있을 것 같습니다.
감사합니다!