728x90
반응형
SMALL
Optional 이란?
- 자바의 가장 큰 고질적인 문제가 바로 null 체크 였다고 한다.
- 이를 해결하기 위해 값이 1개 있거나 없을 수 있는 클래스를 만듦
- Java8부터 지원하는 Optional 클래스
- NPE (NullPointer Exception) 를 피하기 위해 Null 값을 감쌀 수 있는 Wrapper Class 이다.
- Optional<T>
class Optional<T> {
T value;
....
}
Optional 없는 NullCheck
- 아래와 같은 User 클래스가 있다.
public class User {
private String address;
public String getAddress() {
return this.address;
}
public void setAddress(String address) {
this.address = address;
}
}
- 만약 User 객체에서 address를 접근하고자 할때, 객체가 null 인 경우를 배제 할 수 없다.
User user = getUser();
String address = user.getAddress() // 만약 유저가 null 이라면 NPE 발생
//null 체크하는 코드
if(user != null) {
if(address != null){
address = user.getAddress()
}
}
- 위와 같은 방법으로 null 체크를 해야하고 null체크를 하면서 코드가 조금 지저분해진 느낌을 받을 수 있다.
- 또한, address가 String이 아닌 또 하나의 클래스였고 그 안에 또 멤버 변수들이 있었다면 null 체크는 더 복잡해 졌을 것으로 보여진다.
Optional 생성 메소드
- Optional.of(value) : value 가 null이면 NPE 발생
- Optional.ofNullable(value) : value 가 null이면 empty Optional 생성
- Optional.empty() : empty Optional 생성
String str = "hello";
Optional<String> o1, o2, o3;
// 1. Optional.of(value) 를 사용하여 생성
o1 = Optional.of(str);
System.out.println(o1); // Optional[hello]
System.out.println(o1.get()); // "hello"
// o1 = Optional.of(null); // of(value) 의 value 가 null이면 NPE 발생
// 2. Optional.ofNullable(value)
// value 가 null이면 empty Optional 객체 반환
o2 = Optional.ofNullable(str);
System.out.println(o2);
System.out.println(o2.get());
o2 = Optional.ofNullable(null); // null 가능!
System.out.println(o2); // Optional.empty
//System.out.println(o2.get()); // 에러 NoSuchElementException: No value present
// 3.Optional.empty() empty Optional 객체 반환
o3 = Optional.empty();
System.out.println(o3); // Optional.empty
- 위와 같은 3가지 방법으로 Optional 생성 할 수 있다.
More
- 만약 담아야 하는 값들이 기본 자료형이고 이를 위해 Wrapper 클래스를 사용해야 한다면
- EX) Optional<Integer>, Optional<Long>
- 위의 예시 처럼 사용하지 말고
- OptionalInt, OptionalLong 등을 사용할 수 있다.
Optional<Integer> optInteger = Optional.of(10); // boxing 발생
OptionalInt optInt = OptionalInt.of(10); // boxing 발생 안함.
OptionalLong optLong = OptionalLong.of(1234L);
OptionalDouble optionalDouble = OptionalDouble.of(3.14);
System.out.println(optInteger.get() + 0); // unboxing 발생
System.out.println(optInt.getAsInt() + 0); // unboxing 발생 안함.
System.out.println(optionalDouble.getAsDouble());
System.out.println(optLong.getAsLong());
Optional 주요 메소드
주요 메소드 | ||
isPresent() | boolean | 내부 객체가 null 인지 아닌지 확인 null 이면 false 반환 |
ifPresent(Consumer<T>) | void | Consumer<T>는 함수형 인터페이스로 void 추상 메소드를 가지고 있으며, null이 아닐 때만 실행 |
filter(Predicate<T>) | Optional<T> | 내부 객체가 Predicate<T>(리턴 타입 boolean)를 만족 하는지 확인 |
map(Functional<T, U>) | Optional<U> | stream과 같이 내부 객체를 변환 하는 용도로 사용한다. |
get() | T | 내부 객체를 반환한다. 내부 객체가 null 이면 NPE null 이 아닌 경우에만 사용해야한다. |
orElse(T) | T | 내부 객체를 반환 하고, 내부 객체가 null 이면 인자로 들어간 기본값을 반환한다. |
orElseGet(Supplier<T>) | T | orElse() 와 동일하지만 orElseGet()은 내부 객체가 null 일때 기본 값을 반환할 객체를 인자로 받는다. |
orElseThrow(Supplier<U>) | T | 내부 객체가 null 이면 인자로 전달받은 예외를 발생 시킨다. |
public class Address {
private String street;
public Address(){}
public Address(String street) {
this.street = street;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
@Override
public String toString() {
return String.format("[Address: street=%s]", this.street);
}
}
- 위와 같은 클래스가 있을 때, Optional 클래스를 어떻게 사용 할 수 있는 지 사용해 보도록 하겠다.
Address addr1 = new Address("역삼로");
Address addr2 = null;
Optional<Address> optAddr1, optAddr2;
//생성할 때, of() 안에 null 이면 NPE
// optAddr2 = Optional.of(addr2); // NPE 발생
optAddr2 = Optional.ofNullable(addr2); //Optional.Empty 생성
System.out.println(optAddr2.isEmpty()); // true
System.out.println(optAddr2.isPresent()); // false
optAddr1 = Optional.of(addr1);
System.out.println(optAddr1.isEmpty()); // false
System.out.println(optAddr1.isPresent()); // true
optAddr1.ifPresent(s -> System.out.println("주소:" + s));
optAddr1.ifPresent(s -> System.out.println(s));
optAddr1.ifPresent(System.out::println);
System.out.println(optAddr1.get());
// System.out.println(optAddr2.get()); // // NoSuchElementException 발생
System.out.println(optAddr1.orElse(new Address("UNKNOWN"))); // orElse(T)
System.out.println(optAddr2.orElse(new Address("UNKNOWN")));
System.out.println(optAddr2.orElseGet(() -> new Address("몰라요")));
// optAddr2.orElseThrow(); // NoSuchElementException 발생
// optAddr2.orElseThrow(() -> new NullPointerException());
System.out.println(optAddr1.filter(s -> s.getStreet().equals("역삼로")));
System.out.println(optAddr1.filter(s -> s.getStreet().equals("강남대로"))); // Optional.empty
System.out.println(optAddr1.map(s -> s.getStreet().length())); //Optional[3]
Optional 클래스가 지원하는 메소드들을 통해 Java에서 객체의 null 체크를 방법들에 대해서 정리 하였다.
728x90
반응형
LIST
'프로그래밍 > 자바' 카테고리의 다른 글
[자바/기본] Stream 사용하는법 (Feat. Java) (1) | 2024.02.21 |
---|---|
[자바/기본] Stream 이란? (0) | 2024.02.20 |
[자바/기본] 람다식 (Lambda) 란? (0) | 2024.02.16 |
[자바/기본] 내부 클래스(InnerClass) (0) | 2024.02.14 |
[자바/기본] List 란? (0) | 2024.02.13 |