베어_
TechBear
베어_
전체 방문자
오늘
어제
  • 분류 전체보기 (336)
    • Spring (33)
      • 개념 (13)
      • Security (5)
      • 실습 (1)
      • 토비 스프링 (11)
    • JPA (6)
    • 프로젝트 기록 (24)
    • DB (13)
    • JAVA (18)
    • 알고리즘 (50)
      • 유형정리 (8)
      • Baekjoon (21)
      • LeetCode (18)
    • 디자인패턴 (0)
    • 개발서적 (79)
      • Effective Java (78)
      • 객체지향의 사실과 오해 (1)
    • 독후감 (4)
    • 보안 (2)
    • 운영체제(OS) (53)
      • 공룡책 (53)
    • 컴퓨터 네트워크 (28)
      • 컴퓨터 네트워크 하향식 접근 (23)
    • 자료구조 (1)
    • DevOps (2)
    • 앱 개발 (20)
      • 안드로이드 스튜디오 (20)

블로그 메뉴

    공지사항

    인기 글

    태그

    • 이펙티브자바
    • 자바8
    • 알고리즘
    • 운영체제
    • Spring
    • leetcode
    • 토비스프링
    • 코드업
    • java
    • 스프링
    • jpa
    • 스레드
    • BFS
    • 함수형인터페이스
    • 데이터베이스
    • dfs
    • 스프링시큐리티
    • 자바
    • 백준
    • C++

    최근 댓글

    최근 글

    티스토리

    hELLO · Designed By 정상우.
    베어_

    TechBear

    [Java] Optional의 개념과 사용
    JAVA

    [Java] Optional의 개념과 사용

    2022. 5. 20. 11:07

    Optional의 등장

       프로그래밍을 하다보면 NullPointException을 종종 보게 된다. null을 리턴하면 안되는데 null을 리턴하는 경우 생기는 예외인데, 이를 처리하는 방법은 크게 2가지가 있다.

    • 예외를 던지는 방법
    public Something getSomething() {
    	if(this.something == null) throw new IllegalStateException();
    	return something;
    }

    예외를 던질 때 자바는 stack trace에 대한 정보를 생성하고 보여주는데, 이는 리소스를 사용하기 때문에 로직 처리에 예외 처리를 하지 않는 것이 좋다. 따라서 클라이언트 코드가 null을 체크하는 방법을 주로 사용한다.

     

    • 클라이언트 코드가 null을 체크하는 방법
    Progress progress = spring_boot.getProgress();
    if(progress != null) {
        System.out.println(progress.getStudyDuration());
    }

    위와 같은 코드를 더욱 더 명시적으로 표현하고, null을 잘 처리하기 위해 자바8 에서는 Optional<T>을 제공한다. 

     

     

    Optional의 기본 사용

    연습에 사용될 간략화 된 코드는 다음과 같다. OnlineClass는 id, title, closed, progress 멤버변수와 getter, setter를 가지고 있다. 

    Optional1은 값을 가지고 있고, Optional2는 값을 가지고 있지 않다.

    public class OnlineClass {
        private Integer id;
        private String title;
        private boolean closed;
        public Progress progress;
    }
    
    List<OnlineClass> springClasses = new ArrayList<>();
    springClasses.add(new OnlineClass(1, "spring boot", true));
    springClasses.add(new OnlineClass(5, "rest api development", true));
    
    Optional<OnlineClass> optional = springClasses.stream()
            .filter(oc -> oc.getTitle().startsWith("spring"))
            .findFirst();
    
    Optional<OnlineClass> optional2 = springClasses.stream()
            .filter(oc -> oc.getTitle().startsWith("jpa"))
            .findFirst();

     

    isPresent()

       isPresent()는 현재 Optional에 값이 들어있는지 확인하고 boolean값으로 리턴하는 함수이다. 

    boolean flag = optional.isPresent();
    System.out.println("spring 포함한 title 있음 = " + flag);

     

    get()

       get()은 현재 Optional안에 객체가 있으면 리턴하고, 없으면 RuntimeException을 발생시킨다. get()의 경우 다른 api로 커버할 수 있으므로 사용을 최대한 자제해야 한다.

    OnlineClass oc = optional.get();
    System.out.println(oc.getId() + " " + oc.getTitle());
    
    OnlineClass oc2 = optional2.get(); // 비어있기 때문에 RuntimeException 발생

     

    ifPresent()

       Consumer람다식을 쓸 수 있으며 if문을 쓰지 않고 간편하게 처리 할 수 있다.

    if(optional.isPresent()) {
        System.out.println(optional.get().getTitle());
    }
    
    // 위의 코드를 다음과 같이 간편하게 표현할 수 있다.
    optional.ifPresent(p -> p.getTitle());

     

    orElse()

       만약 객체가 비어있으면 Else()문 안의 코드를 실행한 뒤 리턴한다.

    OnlineClass onlineClass1 = optional.orElse(createNewClass());
    System.out.println(onlineClass1.getTitle());
    
    OnlineClass onlineClass2 = optional2.orElse(createNewClass());
    System.out.println(onlineClass2.getTitle());

    출력값

    createNewClass()는 "creating new class" 출력하고 새로운 class를 생성하는 코드이다. 그런데 onlineClass1은 값이 있는데 createNewClass()가 실행된 것을 확인할 수 있다.

     

    이럴 때ㅐ 사용할 수 있는 것이 orElseGet이다.

     

    orElseGet()

       함수형 인터페이스로 supplier를 사용한다. supplier는 lazy evaluation이 필요할 때 주로 이용되는데 이는 다음 포스팅을 참고하자.

    OnlineClass onlineClass3 = optional.orElseGet(OptionalMain::createNewClass);
    System.out.println(onlineClass3.getTitle());

     

    orElseThrow() 

       Optional에 값이 있으면 가져오고 없으면 에러를 발생시킨다.

    OnlineClass onlineClass4 = optional2.orElseThrow();

     

    filter(Predicate) 

       Optional에서도 filter를 사용할 수 있다. 

    Optional<OnlineClass> onlineClass = optional.filter(OnlineClass::isClosed);
    System.out.println(onlineClass.isPresent());

     

    map(Function)

    Optional<String> title = optional.map(OnlineClass::getTitle);
    System.out.println(title.get());

     

    flatMap

       map의 리턴 값으로 Optional<>이 리턴 된다면 다음과 같이 두 번 Optional을 벗겨내는 일을 해야 한다.

    Optional<Optional<Progress>> progress = optional.map(OnlineClass::getProgress);
    Optional<Progress> progress1 = progress.orElseThrow();
    Progress progress2 = progress1.orElseThrow();

     

      flatMap은 이런 과정을 줄여준다.

    Optional<Progress> progress3 = optional.flatMap(OnlineClass::getProgress);
      'JAVA' 카테고리의 다른 글
      • [Java] 자바의 가비지 컬렉션
      • [Java] JVM이란?
      • [Java] Supplier 함수 인터페이스와 Lazy Evaluation
      • [Java] 자바에서 제공하는 함수형 인터페이스
      베어_
      베어_
      Today I learned | 문제를 해결하는 개발자

      티스토리툴바