<피드백 언제나 환영합니다! 댓글 달아주세요 감사합니다>
Java Optional 1 에서 정확한 설명을 하지 못해서 보충 설명 및 사용시 주의사항 위주로 이야기 해보려고 합니다.
- orElse, orElseGet두 메소드의 차이점을 쉽게 생각하려다보니 놓친 부분이 있다.orElseGet(Supplier ...) → other.get()이 실행이된다 → value 값이 null 인 경우에 method 가 실행이 되는형태 (method 가 들어온 형태라면)
- orElse(T other) → 안에 있는 값이 무조건 실행되는걸 확인할 수있다. 즉, println() 과 같은 형태이다. 즉 T other 에 method가 들어간 형태이기 때문 (반환값이 있는)
- Optional.steam() 통해 스트림을 생성(Java 9부터 추가) → Optional은 stream용 메서드가 아니다.
Java Optional 주의사항
앞전에도 말했듯이 Optional은 Wrapper class 입니다 → Wrapper class 는 비용문제가 발생 → 객체 생성, 참조 비용...
primitive type 비해 비싸다 필요할 때만 써야합니다. Effective Java 에서 Optional 활용에 따르면
- Optional 활용1 - 기본값(defalut)를 정해둘 수 있다.
optionalS1.orElse(”이름 없음”);
- Optional 활용2 - 원하는 예외를 던질 수 있다.
- 값이 없는경우 원하는 예외를 던져 사용이 가능하다
optionalS1.orElseThrow(Exception::new);
- Optional 활용3 - 항상 값이 채워져 있는 경우
- .get()을 이용하여 출력 → 값이 있다고 확신이 들때만 사용
- Optional 활용4 - 기본값을 설정하는 비용이 큰 경우
- 활용1 에서 기본값 비용이 클경우 사용
Java Optional 안티 패턴
- Collection, Stream, 배열은 Optional로 되도록이면 감싸지 말자
- List 는 값을 담아두는 그릇 → 빈 ArrayList를 반환하면 된다. → Optional 처리코드를 넣지 않아도 된다.
- Optional을 Map의 키나 값으로 사용 금지
- key 자체가 없는경우
- key는 있지만, 속이 빈 Optional 인경우
- isPresent() 를 사용하지 말자
- if 문을 벗어나기위해 Optional을 사용한거다.. 이점을 꼭 생각해야 한다.
추가적으로 알아야 할 것들
- 박싱된 기본타입 사용시 → OptionalInt, OptionalDouble, OptionalLong 사용
- 값을 반환하지 못할 가능성이 있고, 호출할 때마다 반환값이 없을 가능성을 염두에 둬야하는 메소드 → Optional을 반환해야하는 상황일 수 있다. (JpaRepository save() 같은 기능들)
추가 Optional Method
Java Optional 1 :: Eco 의 개발일기 에서 get(), orElseThorw(), orElse(), orElseGet()외 다른 method를 확인 해보겠습니다.
예제 class
@Data static class Team{ Subject subject; List<Member> memberList; } @Data static class Subject{ String gameName; } @Data static class Member { Long id; String name; String email; }
- void ifPresent(Consumer<? super T> consumer)
- Optional 내부의 값이 있는 경우 consumer 함수를 실행
- Optional<T> filter(Predicate<T> predicate)
- Optional에 filter 조건을 걸어 조건에 맞을 때만 Optional 내부 값이 있음
- 조건이 맞지 않으면 Optional.empty를 리턴
Optional.filter() 예제
Member member1 = new Member(1L, "hello1"); Member member2 = new Member(null, null); List<Member> memberList = new ArrayList<>(List.of(member1, member2)); Subject subject = new Subject(); subject.setGameName("LOL"); Team team = new Team(); team.setMembers(memberList); team.setSubject(subject); Team team1 = Optional.ofNullable(team) .filter(item -> item.getSubject().getGameName().equals("LOL")) .orElse(null); System.out.println("team1 = " + team1); /*team1 = OptionalJava.Team(subject=OptionalJava.Subject(gameName=LOL), members=[OptionalJava.Member(id=1, name=hello1, email=null), OptionalJava.Member(id=null, name=null, email=null)]) /*
- Optional<U> map(Funtion<? super T, ? extends U> f)
- Optional 내부의 값을 Function을 통해 가공
- Optional.empty를 리턴
Optional.map() 예제
Team team = new Team(); String gameObject = Optional.ofNullable(team) .map(Team::getSubject) .map(Subject::getGameName) .orElse("game 종목이 없네"); System.out.println("gameObject = " + gameObject ); /* 게임종목이 없네/*
- Stream을 이용한 Optional중간에 비어있는 Optional 객체가 반환되는 경우, Stream.empty()가 반환되며 함수 체이닝이 더 이상 진행되지 않는점을 유의하자. 스트림 연산이 멈춘다.
Stream 예제 코드
List.of(4, 3, 2, 5) .stream() // stream으로 복사해서 사용가능하다. .map(value -> value > 2 ? Optional.of(value) : Optional.empty()) .flatMap(Optional::stream) .forEach(System.out::println); /* 3 4 5 */
참고
Uploaded by Notion2Tistory v1.1.0