본문으로 건너뛰기

Optional 기본

원시형에도 Optional을 사용가능

int, long, double 등의 원시형 데이터를 다룰 때에는
OptionalInt, OptionalLong, OptionalDouble와 같은 전용클래스를 이용하면 랩퍼 형으로 형변환을 하지 않아도 되므로 효율적인 옵셔널을 사용하기에 좋다.
원시형 데이터 에서의 Null을 다룰 때에는 꼭 써보자

옵셔널 오브젝트의 생성법

public class Exercise1 {

public static void main(String[] args) {

// of의 경우에는 직접 null을 넣으면 예외로 스로우 된다.
Optional<String> exist = Optional.of("abc");
System.out.println(exist);


// 값을 갖고 있지 않은 비어있는 옵셔널 오브젝트 생
Optional<String> empty = Optional.empty();
System.out.println(empty);

// 값이 null이외일경우 에는 값을 갖고 있는 옵셔널,
// 값이 null일 때에는 비어있는 옵셔널이 된다.
String value = "";
Optional<String> optional = Optional.ofNullable(value);
System.out.println(optional);
value = null;
System.out.println(optional);

// 제일 위에 코드에 null을 직접 대입해보자
Optional<String> exist2 = Optional.of(null);
System.out.println(exist2);

}
}
Optional[abc]
Optional.empty
Optional[]
Optional[]
Exception in thread "main" java.lang.NullPointerException
at java.util.Objects.requireNonNull(Objects.java:203)
at java.util.Optional.<init>(Optional.java:96)
at java.util.Optional.of(Optional.java:108)
at MapExercise.Exercise1.main(Exercise1.java:27)

옵셔널 로부터 값을 갖고 오는 법

public class Exercise1 {

public static void main(String[] args) throws Exception {

String name = "James";
Optional<String> optionalName = Optional.ofNullable(name);

// String name 값이 null일경우 NoSuchElementException으로 스로우 된다
String value1 = optionalName.get();


// 값이 null일경우 공문자를 반환한다
String value2 = optionalName.orElse("");

// 값이 null일경우 람다식 결과를 반환한다
String value3 = optionalName.orElseGet(() -> {
return new SimpleDateFormat("yyyyMMddHHmmSS").format(new Date());
});

// 값이 null일경우 임의 지정 예외 처리를 한다
String value4 = optionalName.orElseThrow(() -> new Exception("값이 없습니다"));

}
}

nullpoint익셉션 에러를 피하기 위해서 옵셔널을 쓰는데..
첫번째 코드는 사실상 안쓰일것 같다..? (익섹셥이 발생하니까..)
orElse / orElseGet / orElseThrow 모두 많이 보이기 때문에 필히 익혀두자

값이 있는경우만 처리하기 !(null이 아닐때에만)

public class Exercise1 {

public static void main(String[] args) throws Exception {

String name = "James";

Optional<String> nullableName = Optional.ofNullable(name);

if (nullableName.isPresent()) {
System.out.println(nullableName.get());
} else {
System.out.println("값이 없으면 처리가 이쪽으로 빠져요");
}

String name2 = null;

Optional<String> nullableName2 = Optional.ofNullable(name2);

if (nullableName2.isPresent()) {
System.out.println(nullableName2.get());
} else {
System.out.println("값이 없으면 처리가 이쪽으로 빠져요");
}

}
}
James
값이 없으면 처리가 이쪽으로 빠져요

실무에서 쓰면 아주아주아주 유용할 기술이다

값이 있는 경우에만 람다로 처리하기

public class Exercise1 {

public static void main(String[] args) throws Exception {

String name = "James";
Optional<String> nullableName = Optional.ofNullable(name);

nullableName.ifPresent(s -> System.out.println(s));

String name2 = null;
Optional<String> nullableName2 = Optional.ofNullable(name2);

nullableName2.ifPresent(s -> System.out.println(s));
}
}
James

두번째는 null이므로 람다 처리가 되지 않았다. 이것도 실무에 쓰면 아주 유용할듯

옵셔널과 필터링의 조합

filter()메서드를 사용하면.
조건에 부합할 때 처리 / 조건에 부합하지 않으면 비어있는 옵셔널 반환 식으로 사용할 수 있다.

public class Exercise1 {

public static void main(String[] args) throws Exception {

String name = "James";
Optional<String> nullableName = Optional.ofNullable(name);

nullableName.filter(s -> s.length() > 4)
.ifPresent(p -> {
System.out.println(p);
});

nullableName.filter(s -> s.length() > 5)
.ifPresent(p -> {
System.out.println(p);
});

nullableName.filter(s -> s.length() >= 5)
.ifPresent(p -> {
System.out.println(p.toUpperCase());
});
}
}

James
JAMES

옵셔널과 map 조합으로 새로운 옵셔널에 맵핑

public class Exercise1 {

public static void main(String[] args) throws Exception {

String name = "James";
Optional<String> nullableName = Optional.ofNullable(name);

Optional<String> mappedName = nullableName.map(s -> s.toUpperCase());

mappedName.ifPresent(s -> System.out.println(s));


String name2 = null;
Optional<String> nullableName2 = Optional.ofNullable(name2);

Optional<String> mappedName2 = nullableName2.map(s -> s.toUpperCase());

mappedName2.ifPresent(s -> System.out.println(s));

}
}
JAMES

두번째는 null이므로 출력이 안된다(비어있는 옵셔널 객체)

복수의 옵셔널을 동시에 사용해보기

public class Exercise1 {

public static void main(String[] args) throws Exception {

String userName = "David";
String password = "Father";
Optional<String> nullableName = Optional.ofNullable(userName);
Optional<String> nullablePassword = Optional.ofNullable(password);

boolean isValid = nullableName.flatMap(n -> {
return nullablePassword.map(p -> {
return n.equals("David") && p.equals("Father");
});
}).orElse(false);

System.out.println(isValid);

// 한쪽에 null을 넣어봄
String idCard = null;
String cardPassword = "Brother";
Optional<String> nullableIdCard = Optional.ofNullable(idCard);
Optional<String> nullableCardPassword = Optional.ofNullable(cardPassword);

boolean getValidInform = nullableIdCard.flatMap(n -> {
return nullableCardPassword.map(p -> {
return n.equals("Joly") && p.equals("Brother");
});
}).orElse(false);

System.out.println(getValidInform);
}
}
true
false

한쪽에 null이 있을경우 비어있는 옵셔널이 반환되므로
orElse메서드의 디폴드 값인 false가 최종적으로 반환된다