Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 벌크연산
- 페치조인
- LIST
- javaservlet
- values()
- joinfetch
- 페이징
- 프로젝트생성
- jQuery값전송
- 제너릭
- fetchjoin
- 엔티티직접사용
- namedQuery
- Generic
- 자바서블릿
- 제네릭
- paging
- jQuery값전달
- 스프링데이터흐름
- Hibernate
- JQuery
- JPA
- javascriptcalendar
- 대량쿼리
- fullcalendar
- jscalendar
- springflow
- jQueryUI
- calendar
- JPQL
Archives
- Today
- Total
가자공부하러!
모던자바인액션(CH11) - Optional 본문
목차
요약 및 결론
책 내용
요약 및 결론
- Optional은 만능이 아니다. null 체크는 Optional이 있든 없든 더럽다.
- 'null일 수도 있는 값이다'라는 의미를 전달하는 역할이 중요한 듯 하다.
- flatMap 연결, ifPresent은 참 좋아 보인다.
책 내용
Optional 클래스
- 선택형값을 캡슐화하는 클래스
- 값이 있는 경우 : Optional 클래스는 값을 감싼다
- 값이 없는 경우 : Optional을 반환
- 모든 null 참조를 Optional로대치하는 것은 바람직하지 않다.
- Optional의 역할은 더 이해하기 쉬운 API를 설계하도록 돕는 것이다.
- 선택형값을 캡슐화하는 클래스
Optional 적용 패턴
Optional 객체를 만드는 여러 방법
@Test void makeOptional() { // 빈 Optional 객체 Optional<Cars> empty = Optional.empty(); // null이 아닌값으로 Optional 만들기 // of()는 null이 아닌 값을 포함하는 Optional을 반환해주는 메소드이기 때문에 car가 null이면 즉시 NPE 발생 // Objects 클래스에서 NPE throw Cars car = null; Optional<Cars> notNullCar = Optional.of(car); // NPE! // null값을 저장할 수 있는 Optional을 만드는 ofNullable() Optional<Cars> nullableCar = Optional.ofNullable(car); }
Optional 객체의 값을 다루는 여러 방법
@Test void treatValuesByOptionalMapTest() { // Optional.map() Cars car = null; Optional<String> optionalModel = Optional.ofNullable(car).map(Cars::getModel); log.info("optional model : {}", optionalModel); // 결과 : optional model : Optional.empty String nullString = null; Optional.ofNullable(nullString).ifPresent(optional -> log.info("is present : {}", optional)); // 결과 : 출력 없음 String notNullString = "str"; Optional.ofNullable(notNullString).ifPresent(optional -> log.info("is present : {}", optional)); // 결과 : is present : str }
Optional.flatMap() 활용방법 : 중첩Optional 제어
@Test void flatMapTest() { Insurance insurance = Insurance.builder().name("삼성화재").build(); Car car = Car.builder().insurance(insurance).name("기블리").build(); Person person = Person.builder().car(car).name("민형준").build(); // Optional 없이 insurance의 name 확인 if (person.getCar() != null) { if (car.getInsurance() != null) { log.info("insurance : {}", insurance.getName()); } else { log.info("Unknown"); } } // 컴파일 불가 // Optional<String> insuranceName = Optional.of(person) // .map(Person::getCar) // Optional<Optional<Car>>를 리턴 // .map(Car::getInsurance) // .map(Insurance::getName); String unknown = Optional.ofNullable(person) .flatMap(Person::getCar) .flatMap(Car::getInsurance) .map(Insurance::getName) .orElse("Unknown"); log.info("unknown : {}", unknown); }
디폴트 액션과 Optional 언랩
@Test void defaultActionAndUnwrap() { // 값이 있느냐 없느냐의 기준은 null이냐 아니냐 Person getTestPerson = new Person(); Optional.ofNullable(getTestPerson).get(); // 통과 getTestPerson = null; // Optional.ofNullable(getTestPerson).get(); // NoSuchElementException // Optional<Person> optionalPerson = Optional.ofNullable(person); // get() : 래핑된 값이 있으면 해당 값을 반환하고, 값이 없으면 NoSuchElementException 발생 optionalPerson.get(); // orElse() : 값 없을 때 리턴할 대체값을 매개변수로 전달 optionalPerson.orElse(new Person()); // orElseGet() : orElse의 매개변수는 Optional의 값이 있든 없든 항상 호출되지만 orElseGet은 Optional의 값이 없으면 호출안됨 // Person.newInstance(String num)은 num을 출력하고 빈 Person객체를 생성해서 리턴해주는 스태틱 메소드 optionalPerson.orElse(Person.newInstance("1'")); // 결과 : num : 1 optionalPerson.orElseGet(() -> Person.newInstance("2")); // 결과 : 출력 없음 // orElseThrow() : Optional이 비었을 때 매개변수로 들어간 예외 발생 optionalPerson.orElseThrow(() -> new NumberFormatException()); // ifPresent() : 값이 존재할 때 인수로 넘겨준 동작 실행 optionalPerson.ifPresent(person -> log.info("is present")); // [Java 9]ifPresentOrElse() : Optional이 비었을 때 실행할 수 있는Runnable을 받음 }
두 Optional 합치기
@Test void mergeOptionalObjects() { Optional<Person> optionalPerson = Optional.ofNullable(this.person); Optional<Car> optionalCar = Optional.ofNullable(this.car); // 합체없음 if (optionalPerson.isPresent() && optionalCar.isPresent()) { Optional.of(findCheapestInsurance(optionalPerson.get(), optionalCar.get())); } // 합체 // p가 빈 Optional이면 빈 Optional 반환, c가 빈 Optional이면 빈 Optional 반환 // 둘 중 하나라도 빈 Optional이면 빈 Optional을 반환하고 아니면 findCheapestInsurance수행 optionalPerson.flatMap(p -> optionalCar.map(c -> findCheapestInsurance(p, c))); } private Optional<Insurance> findCheapestInsurance(Person person, Car car) { return car.getInsurance(); }
Optional.stream()은 자바 9 부터 제공
Optional 실용 예제
- 잠재적으로 null이 될 수 있는 대상 Optional로 감싸기
@Test void wrapNullableValue() { // Map에서 key없는경우 위험부담 줄이기 Map<String, Person> map = new HashMap(); Optional<Person> optionalPerson = Optional.ofNullable(map.get("a")); }
- 예외와 Optional 클래스
- Optional과 예외 함께 활용
public static Optional<Integer> stringToInt(String s) { try { return Optional.of(Integer.parseInt(s)); } catch (NumberFormatException e) { return Optional.empty(); } }
- Optional과 예외 함께 활용
- 기본형 Optional을 사용하지 말아야 하는 이유
- Stream이 많은 요소에서는 기본형 특화 스트림이 성능개선에 좋지만, Optional의 최대 요소 수는 한 개 이므로 성능 개선 불가
- 기본형 특화 스트림은 map(), flatMap(), filter()등을 지원하지 않음
@Test void primitiveOptionalTest() { OptionalInt.of(5).equals(1); OptionalInt.of(5).getAsInt(); OptionalInt.of(5).ifPresent(i -> log.info("ok")); OptionalInt.of(5).isPresent(); OptionalInt.of(5).orElse(1); OptionalInt.of(5).orElseGet(() -> new Integer(1)); OptionalInt.of(5).orElseThrow(() -> new NumberFormatException()); }
- 잠재적으로 null이 될 수 있는 대상 Optional로 감싸기
Optional과 Serialize
- Optional의 용도는 선택형 반환값을 지원하는 것이다.
- Serializable을 구현하지 않는다.
- 실제로 String, Integer(Number) 등은 Serializable을 구현하고 있다.
- 필드 형식으로 사용할 것을 가정하지 않았기 때문에 모델에 Optional을 필드로 둔다면 직렬화 과정에 문제가 생길 수 있다.
- 무슨 문제? 인지는 모르겠음
- 조금 찾아보니 필드로 선언 하라고 만든게 아닌데 굳이 왜 쓰느냐 라는 식임
'공부 > Java' 카테고리의 다른 글
모던자바인액션(CH13) - 디폴트 메서드 (0) | 2020.08.12 |
---|---|
모던자바인액션(CH12) - 새로운 날짜 시간 API (0) | 2020.08.05 |
모던자바인액션(CH10) - 람다를 이용한 도메인 전용 언어(DSL) (0) | 2020.06.24 |
Hibernate에서 uuid와 uuid2의 차이점(스크랩) (0) | 2020.06.16 |
모던자바인액션(CH9) - 스트림과 람다 활용(2) (0) | 2020.06.13 |
Comments