java로 프로그래밍하다보면 심심찮게 NullPointerException을 겪게 된다. 꼼꼼하게 설계하고, null관련 처리를 하면 된다곤 하지만, 현실은 녹록치 않다. 다른 사람이 만든 클래스를 사용하는데 문서화가 덜 되었다던가, 너무 복잡하다던가, 파악하기 귀찮다던가한 이유로 NPE를 뿜어내는 코드를 작성하게 된다.
이런 문제를 해결하기 위해 Java 8에서 Optional 이라는 클래스가 추가되었다.
Optional은 쉽게(?) 말하자면 "데이터가 없다"는 null 아닌 data를 만들고, 이것을 handling 하는 기능이 있는 클래스라고 할 수 있다.
아래는 Optional을 만드는 예시 java 코드다.
Optional<String> s1 = Optional.empty(); // 원래는 null인 경우
Optional<String> s2 = Optional.of("Hello"); // NPE if input is null
Optional<String> s3 = Optional.ofNullable("World"); // null input이면 empty 반환
또한 아래와 같이 Optional class를 변환 및 필터링할 수 있다.
s1.map(it -> it + " op"); // empty
s3.map(it -> it + " op"); // "World op"
s2.flatMap(it -> other); // other
s2.filter(it -> it.startsWith("H")); // Hello
s3.filter(it -> it.startsWith("H")); // empty
그리고 아래와 같이 Optional class를 unwrapping 해서 원래 type의 data를 얻을 수 있다.
s1.orElse("empty"); // empty
s1.orElseThrow(RuntimeException::new) // RuntimeException
s2.orElse(null); // Hello
s3.orElseGet(() -> "empty"); // World
마지막으로 아래와 같이 값이 존재하는지 조건문을 쓸 수 있다.
s1.ifPresent(it -> {
System.out.println("not Empty");
}); // nothing happens
s2.ifPresent(it -> {
System.out.println("not Empty " + it);
}); // not Empty Hello
s1.isPresent() // false
s2.isPresent() // true
Optional 클래스는 자바 버전에 따라 기능이 추가되기도 하였고, 이것 외에도 기능이 많다. 그러므로 Optional 클래스의 상세 스펙이나 자세한 정보는 관련 공식 문서나 블로그 포스트들을 찾아보면 된다.
kotlin에는 Optional 클래스가 따로 없다. 왜냐하면 굳이 필요가 없기 때문이다(!!). kotlin은 Optional 대신 변수(프로퍼티)의 타입을 nullable하게 지정해서 null 관련 연산자를 이용한다.
아래는 kotlin의 nullable로 위에 있던 java code를 작성한 것이다.
val s1: String? = null
val s2: String? = "Hello" ?: throw NullPointerException()
// 또는 val s2: String = "Hello"
val s3: String? = "World"
위의 Optional 변환 코드를 kotlin nullable을 사용하면 아래와 같을 것이다.
s1?.let {it + "op" }
s3?.let {it + "op" }
s2?.let { other }
s2?.takeIf { it.startsWith("H") }
s3?.takeIf { it.startsWith("H") }
위의 Optional unwrapping 코드를 kotlin nullable을 사용하면 아래와 같을 것이다.
s1?: "empty"
s1?: throw NoSuchElementException()
s2
s3?: run { "empty" }
마지막으로 Optional의 존재 여부 조건문은 아래와 같이 작성할 수 있을 것이다.
s1?.run { println("not Empty") }
s2?.run { println("not Empty $it") }
s1 == null
s2 == null
Optional 대신 kotlin의 nullable을 사용했을 때의 단점은 아래 정도로 생각해 볼 수 있다.
Optional 대신 kotlin의 nullable을 사용했을 때의 장점은 아래 정도로 생각해 볼 수 있다.
!!
로 처리하면 답이 없다.)개인적으로는 위에서 말한 제약 조건이 없다면, kotlin의 nullable을 쓸 것 같다. (RxJava2가 너무 걸리는걸)