728x90
널 참조의 위험성
- 자바를 포함한 많은 프로그래밍 언어에서 가장 많이 발생하는 예외 유형이 NullPointerException이다.
- 줄여서 NPE라고도 부른다
- null을 발명한 토니호어는 1965년 null을 발명한 후 수십 년간 수십억 달러의 시스템 오류와 피해가 발생했기 때문에 1조 원짜리 실수였다고 고백한다.
- 자바에선 NPE를 줄이기 위해 JDK8에서 Optional을 지원하기 시작했다.
- 자바에서 Optional은 값을 래핑 하기 때문에 객체 생성에 따른 오버헤드가 발생하고, 컴파일 단계에서 Null 가능성을 검사하지 않는다.
- 코틀린을 비록 한 최신 언어에선 널 가능성을 컴파일러가 미리 감지해서 NPE 가능성을 줄일 수 있다.
fun getNullStr(): String? = null
fun getLengthIfNotNull(str: String?) = str?.length ?: 0 //엘비스 연산자를 사용해 0 반환
fun main() {
/*
val a: String = null //컴파일 오류 (null을 받을 수 없는 타입이기 때문)
var b: String = "aabbcc"
b = null //컴파일 오류
*/
/*
var a: String? = null //nullable 한 타입
//a.length //nullable 한 타입에 메서드를 쓰면 컴파일 오류
println(a?.length) //컴파일 오류 사라진다 //null 안전 연산자를 사용해 접근하게 되면 nullPoint 예외 없이 사용할 수 있다.
val b: Int = if (a != null) a.length else 0
println(b)
//좀 더 간단한 널 처리가 가능하다.
//엘비스 연산자
val c = a?.length ?: 0 //엘비스 연산자를 사용해 간단한 처리가 가능하다(좌변이 널인 경우 우변 출력)
println(c)
*/
//자바 코드 Kotlin으로 변환
val nullableStr = getNullStr()
//val nullableStrLength = nullableStr.length //컴파일 오류가 발생한다
val nullableStrLength =
nullableStr?.length ?: "null인 경우 반환".length //엘비스 연산자를 통해 "null인 경우 반환".length 실행
println(nullableStrLength)
val length = getLengthIfNotNull(null)
println(length)
//코틀린에서도 NPE를 발생 시킬수 있다.
//throw NullPointerException()
val c: String? = null
//단언 연산자는 null을 없애주는 것이 아니라, 개발자가 핸들링 하도록 하는것이기 때문에 NPE가 발생할 수 있다.
val d = c!!.length //단언 연산자 : 개발자가 봤을때, null이 아님을 확신할 떄 사용하는 연산자
//Java 와 상용운용 하게 되면서, null 참조가 된 코드를 코틀린에서 실행하게 되면, NPE가 발생할 수 있다
}
JAVA 코드
import java.util.Optional;
public class Java_NullSafety {
public static String getNullStr() {
return null;
}
public static int getLengthIfNotNull(String str) {
if (str == null || str.length() == 0) {
return 0;
}
return str.length();
}
public static void main(String[] args) {
String nullableStr = getNullStr();
// Optional 사용
nullableStr = Optional.ofNullable(nullableStr)
.orElse("null 인 경우 반환");
int nullableStrLength = nullableStr.length();
// Optional을 주석처리하고 null 참조를 사용하더라도 컴파일 오류가 발생하지 않음
System.out.println(nullableStrLength);
//메서드 내부에서 null을 검사하는 방법도 있다
int length = getLengthIfNotNull(null);
System.out.println(length);
}
}
- 코틀린은 언어적 차원에서 NPE가 발생할 가능성을 줄인다.
- 코틀린 타입은 기본적으로 Non-Null 타입으로 null을 허용하지 않는다.
- 코틀린은 null을 허용하는 nullable 타입을 제공한다.
- nullable참조는 컴파일 단계에서 널 안정성을 제공
- nullable 참조에 대한 접근은 안전 연산자(?)를 사용한다.
- 엘비스 연산자 (?:)를 사용해 null이 아닌 경우 특정 값을 사용하도록 한다.
- 좌변이 null일 경우 우변을 리턴한다
- 자바에서 Null처리 코드가 코틀린에서는 매우 간단해진 것을 볼 수 있다.
- 코틀린에서도 NPE가 발생할 수 있다.
- 명시적으로 NPE를 호출하는 경우, 단언 연산자(!!)를 사용해 개발자가 직접 핸들링하는데 Null이 반환되는 경우, JAVA와 상호 운용하는 서비스 같은 경우 JAVA에서 NULL을 반환할 경우 NPE가 발생할 수 있다.
- 코틀린에서 자바 코드를 사용할 때는 항상 Nullable 가능성을 염두해 안전 연산자와 엘비스 연산자를 사용
728x90