Optional 클래스
자바 언어로 개발을 하다 보면 항상 조심해야 되는 예외 중에 NullPointer 예외가 있다.
개발하면서 많이 겪는 예외 중에 하나로 왜 null값이 들어올까 항상 고민하게 만드는 예외다.
이러한 문제를 해결해주는 클래스로 Optional 클래스가 있다.
Optional 클래스는 T 타입 객체의 래퍼 클래스로 모든 종류의 객체를 저장할 수 있다.
Optional 클래스를 사용하는 이유
null을 직접 다루는 것은 NullPointer 예외가 발생할 수 있기 때문에 상당히 위험한 행동이다. 따라서 Optional 클래스를 사용해서 null을 간접적으로 다룰 수 있게 해준다.
매개 변수로 들어오는 값이 null인지를 확인하기 위해서는 if문을 통한 검증이 이뤄져야 하고 이로 인해 코드가 지저분해진다. Optional을 통해 해당 검증 과정을 줄임으로써 코드를 간결하게 작성할 수 있다.
Optional 클래스의 메서드 종류
empty() - static 메서드
String opt = null; // 에러는 발생하지 않지만 바람직하지 않음
Optional<String> opt = Optional.empty(); // 이게 더 좋은 방법
우리가 어떤 값을 초기화할 경우 null로 초기화를 할수도 있지만 null을 직접 다룸으로써 예외가 발생할 수 있는 위험이 있기 때문에 간접적으로 다뤄야 한다.
empty() 메서드를 사용하여 값을 초기화할 수 있다.
of() - static 메서드
Optional<String> opt = Optional.of("abc");
값을 넣어서 초기화를 원한다면 of() 메서드를 사용하여 값을 넣어줄 수 있다.
get()
Optional<String> opt = Optional.of("abc");
System.out.println("opt = " + opt.get()); // 값을 가져온다.
get() 메서드는 내가 저장한 값을 모두 가져오는 메서드이다.
해당 코드는 현재 잘 사용되지 않는 방법이다.
orElse()
String str = "";
try { // 이렇게 예외를 처리하면 너무 번거로워진다.
str = opt.get();
} catch (Exception e) {
str = "";
}
System.out.println("str = " + str);
앞서 언급한 get() 메서드를 현재 잘 사용하지 않는 이유는 null을 대비한 예외를 처리해야 되기 때문이다.
따라서 orElse() 메서드를 사용하여 null 값이면 따로 지정한 문자를 반환할 수 있게 코드를 작성할 수 있다.
str = opt.orElse("EMPTY"); // orElse를 사용해서 효과적으로 코드의 수를 줄일 수 있다.
str = opt.orElseGet(() -> "EMPTY"); // 람다식으로 사용할 수 있다.
str = opt.orElseGet(String::new); // 매서드 참조로 바꿀 수 있다.
해당 코드와 같이 orElse() 메서드를 통해서 null값이 들어오면 EMPTY 문장을 반환하게 코드를 작성할 수 있다.
또한 람다식과 메서드 참조도 사용할 수 있다.
filter()
Optional 인스턴스의 값을 주어진 Predicate와 일치시켜 필터링한 다음 필터링된 Optional 클래스를 반환해준다.
만약 Optional 인스턴스에 값이 없으면 빈 Optional 인스턴스를 반환한다.
int result1 = Optional.of("123")
.filter(x -> x.length() > 0)
.map(Integer::parseInt).get();
해당 예제를 살펴보면 먼저 123값을 of() 메서드를 통해서 넣은 다음 filter() 메서드를 사용하여 현재 값의 길이가 0보다 큰지를 확인한다. 예제는 0보다 크기 때문에 filter에서는 Optional 클래스를 반환해주게 된다.
isPresent()
Optional 인스턴스에 값이 있는지 확인하는데 사용되는 메서드로 값이 있으면 true, 없으면 false를 반환한다.
OptionalInt optInt1 = OptionalInt.of(0); // 0이 저장된다.
OptionalInt optInt2 = OptionalInt.empty(); // 빈 객체를 생성한다.
System.out.println("optInt1.isPresent() = " + optInt1.isPresent()); // 같은 0이라면 어떤 것이 빈 객체인지 모르기 때문에 isPresent로 확인해야 한다.
System.out.println("optInt2.isPresent() = " + optInt2.isPresent());
해당 예제를 살펴보면 of() 메서드를 사용해서 0을 저장하는 것과 empty() 메서드를 통해서 빈 객체를 저장하는 것이 서로 같은 0을 저장하는 것처럼 보일 수도 있지만 실제로는 그렇지 않다.
이때 isPresent() 메서드를 사용하여 값을 확인하게 되고 예제에 적용해보면 첫 번째 출력은 true, 두번 째 출력은 false가 나오게 된다.
equals()
Optional이 사용자가 지정한 Optional과 동일하는지 확인하는 메서드로 동일하면 true 값을, 다르면 false 값을 반환한다.
System.out.println("optInt1.equals(optInt2) = " + optInt1.equals(optInt2));
해당 코드도 마찬가지로 같은 0이 아니기 때문에 false 값이 반환된다.
ofNullable()
지정된 유형의 지정된 값을 가진 Optional 클래스의 인스턴스를 가져오는 데 사용된다. 지정된 값이 null인 경우 해당 메서드는 Optional 클래스의 빈 인스턴스를 반환한다.
public static <T> Optional<T> ofNullable(T value) {
return value == null ? (Optional<T>) EMPTY
: new Optional<>(value);
}
메서드를 살펴보면 받아온 value 값이 null인지 확인하여 null이면 Optional 클래스의 빈 인스턴스를 반환해주고 null이 아니면 Optional 클래스의 인스턴스를 반환해준다.
Optional<Integer> test = Optional.ofNullable(425);
System.out.println("test = " + test.orElse(0));
해당 예제를 살펴보면 ofNullable() 메서드에 425 값이 들어감으로써 null이 아니기 때문에 새로운 Optional 클래스의 인스턴스를 반환해주게 된다.
'자바' 카테고리의 다른 글
[Java] - 입출력 스트림 (0) | 2023.11.29 |
---|---|
[Java] - JDK? JVM? JRE? 이게 다 무슨 소리지? (0) | 2023.11.26 |
[Java] - 람다 (0) | 2023.11.17 |
[Java] - 제네릭 (0) | 2023.11.15 |
[Java] - 컬렉션 (0) | 2023.11.14 |