🎯 목표 : 래퍼 클래스 Optional<T> 의 필요성과 활용 이해
📒 Optional<T>
📌 특징
- T타입의 객체를 감싸고 있는 래퍼 클래스다. 모든 타입의 참조변수를 담을수 있다.
- 최종 연산의 결과를 Optional에 담아서 반환하게 되면, 결과가 null인지 if문으로 확인 할 필요가 없으며, Optional의 메소드로 간단하게 확인 할수 있다. NullPointerException을 사전에 방지 할수 있음.
📌 예제
public class StreamOptionalStudy {
public static void main(String[] args) {
Optional<String> optStr = Optional.of("abcde");
Optional<Integer> optInt = optStr.map(String::length);
System.out.println("optStr="+optStr.get()); // 값을 가져올떄 get를 쓴다.
System.out.println("optInt="+optInt.get());
int result1 = Optional.of("123")
.filter(x->x.length() >0)
.map(Integer::parseInt).get(); //get을 사용하게 되면 값이 null 일때 예외가 발생한다.
int result2 = Optional.of("")
.filter(x->x.length() >0) // 길이가 0이기 때문에 false가 되며 필터에 걸러진다.
.map(Integer::parseInt).orElse(-1); // 요소가 없을때 -1을 반환
System.out.println("result1="+result1);
System.out.println("result2="+result2);
Optional.of("456").map(Integer::parseInt)
.ifPresent(x->System.out.printf("result3=%d%n",x)); // null 이면 아무일도 일어나지 않음.
// null이 아닐때 매개변수 수행
}
}
// 출력값
// optStr=abcde
// optInt=5
// result1=123
// result2=-1
// result3=456
- Optional.of 를 사용하여 Optional 객체를 생성할수 있다.
- 객체에 정의된 값을 가져오기 위해서는 get 메소드를 사용하는데 Optional 객체에 null 값이 저장되어 있다면, 예외가 발생하므로 orElse() 메소드로 값을 가져온다. 값이 null 이라면, 대체해서 출력할 값을 매개변수로 지정할수 있다.
- Optional.ifPresent(Consumer<T> c) 메소드는 객체 안에 값이 있다면, 주어진 매개변수 부분을 수행하고, 없다면 아무 작업도 하지 않는다.
- 아래 예제는 isPresent() 메소드를 활용하여 Optional 객체의 값의 유무를 확인 할수 있다.
public class StreamOptionalStudy {
public static void main(String[] args) {
OptionalInt optInt1 = OptionalInt.of(0); // 0을 값으로 정의
OptionalInt optInt2 = OptionalInt.empty(); // 메소드로 빈 객체 선언 기본값 0이 될것이다.
System.out.println(optInt1.isPresent()); // true
System.out.println(optInt2.isPresent()); // false 값이 없다.
System.out.println(optInt1.getAsInt()); // 요소로 0을 가지고 있다.
// System.out.println(optInt2.getAsInt()); // NoSuchElementException
System.out.println("optInt1="+optInt1);
System.out.println("optInt2="+optInt2);
System.out.println("optInt1.equals(optInt2)?"+optInt1.equals(optInt2));
Optional<Object> opt = Optional.empty(); // 메소드로 빈 객체 선언
Optional<Object> opt1 = Optional.ofNullable(null); // null 값을 직접 정의
System.out.println("opt.equals(opt3) = "+opt.equals(opt1)); // 비어 있는것과 동일하다.
}
}
//출력값
// true
// false
// 0
// optInt1=OptionalInt[0]
// optInt2=OptionalInt.empty
// optInt1.equals(optInt2)?false
// opt.equals(opt3) = true
- 기본형을 값으로 하는 OptionalInt 객체에 0을 값으로 정의하고, empty() 메소드로 다른 객체를 하나더 선언 하였다.
- 기본형을 값으로 하기때문에, empty() 메소드로 선언된 객체에는 int의 기본값 0이 정의 되어있을 거라 생각된다.
- 하지만 isPresent() 메소드로 확인 해 보면, 0의 값을 정의한 객체는 true , empty() 메소드로 정의한 객체는 false를 반환한다. 기본형의 OptionalInt 객체라도 empty() 메소드로 정의하게 되면, 기본값을 정의 하는 것이 아닌 비어있는 객체를 만드는거나 마찬가지 인 것을 확인할수 있다. getAsInt() 메소드로 비어 있는 객체의 값을 출력하려고 하면, 예외가 발생하는 것 또한 확인 할수 있다.
- 마지막으로, null 값을 지정한 객체와 empty() 메소드로 값을 지정한 객체는 같다는 것을 확인할수 있다.