NullPointerException 을 발생시킨다.Optional<T>
Optional<T>가Collection<T>를 구현하지는 않았지만 원칙적으로 그렇게 부른다고 한다.
T 를 반환하고 특정조건(null 이 존재할 때)에서는 Optional<T> 를 반환한다.Optional<Object> empty = Optional.empty();
Optional<Object> something = Optional.of(new Object());
/////////////////////
public static <E extends Comparable<E>> Optional<E> max(Collection<E> c) {
if (c.isEmpty())
return Optional.empty();
// Optional<E> 를 반환(비어있는)
E result = null;
for (E e : c)
if (result == null || e.compareTo(result) > )
result = Objects.reuqireNonNull(e);
return Optional.of(result);
// Optional<E> 를 반환(채워있는)
}
null 를 반환하지 않게 설계하자map()이나 flatMap(), filter()와 같은 메소드를 Optional도 가지고 있다/* 주문을 한 회원이 살고 있는 도시를 반환한다 */
public String getCityOfMemberFromOrder(Order order) {
return Optional.ofNullable(order)
.map(Order::getMember)
.map(Member::getAddress)
.map(Address::getCity)
.orElse("Seoul");
}
null 인 경우를 대비하여 of() 대신 ofNullable() 사용map 의 연쇄 사용을 통해 Optinal 객체를 3번 변환Optional<Order> -> Optional<Member> -> Optional<Address> -> Optional<String>orElse() 메소드를 호출하여 Optional이 비어있을 경우, 디폴트로 사용할 서울을 세팅public Optional<Member> getMemberIfOrderWithin(Order order, int min) {
return Optional.ofNullable(order)
.filter(o -> o.getDate().getTime() > System.currentTimeMillis() - min * 1000)
.map(Order::getMember);
}
filter() 메소드는 넘어온 함수형 인자의 리턴 값이 false인 경우, Optional을 비우게 되고 그 이후 메소드 호출은 의미가 없어지게 된다. Optional<Optional<String>> map1 = Optional.of(Optional.of("STRING"));
Optional<Optional<String>> map2 = Optional.of("string")
.map(s -> Optional.of("STRING"));
Optional<String> flatmap1 = Optional.of("STRING");
Optional<String> flatmap2 = Optional.of("string")
.flatMap(s -> Optional.of("STRING"));
String lastWordInLexicon = max(words).orElse("단어 없음...");
Toy myToy = max(toys).orElseThrow(TemperTantrumException::new);
get() : Optional 에 항상 값이 채워져 있다 확신할때 곧바로 값을 꺼낸다. 없을때 NoSuchElementException 이 발생한다. 따라서 ifPresent() 와 같이 쓰이기도 한다.parentProcess.ifPresent() ? String.valueOf(parentProcess.get().pid()) : "N/A"));
orElseGet() : orElseGet은 null일 때만 불린다orElse는 null이던말던 항상 불립니다. - 의도치 않은 함수를 호출할 수 있다!!
orElseGet은 null일 때만 불립니다.
차이점을 꼭 기억하자! -> 플젝때 orElse로 했다가 배포중에 에러가 터진기억이.. ㅠㅠ
public void ohMyGod() {
String username = null;
String result1 = Optional.ofNullable(username).orElse(getDefaultName());
System.out.println(result1);
String result2 = Optional.ofNullable(username).orElseGet(() -> getDefaultName());
System.out.println(result2);
}
private String getDefaultName() {
// 어떤 로직
return "new value";
}
Optional<List<T>> 보다는 그냥 비어있는 List<T> 를 반환하는게 좋다.Optional<T> 를 반환하자Optional 도 새로 할당 후 초기화해야 하는 객체이고 그안에서 값을 꺼내는 단계를 거치므로 성능이 중요할 때는 옵셔널이 좋지 않을 수 있다.
박싱된 기본 타입을 담는 옵셔널은 기본 타입 자체보다 무겁다
OptionalInt, OptionalLong, OptionalDouble 을 제공한다.옵셔널을 컬렉션의 키, 값, 원소나 배열의 원소로 사용하는게 적절한 상황은 거의 없다.
public class EffectiveTest {
@Test
void testtest () {
String name = "1";
Long age = 1L;
TestMember member = new TestMember(1L, Optional.ofNullable(name), Optional.ofNullable(age));
}
static class TestMember{
Long id;
Optional<String> name;
Optional<Long> age;
public TestMember(Long id, Optional<String> name, Optional<Long> age) {
this.id = id;
this.name = name;
this.age = age;
}
}
}