자바 8 딥 러 닝 의 숙달 Optional
1.1 코드 문제 도입
프로그램 을 쓸 때 보통 NullPointer Exception 을 만 났 기 때문에 프로그램 에 대해 비 어 있 는 판단 을 하 는 경우 가 많 습 니 다.
User user = getUserById(id);
if (user != null) {
String username = user.getUsername();
System.out.println("Username is: " + username); // username
}
이러한 난감 한 처 지 를 해결 하기 위해 JDK 는 드디어 자바 8 에 Optional 클래스 를 추가 하여 Optional 의 자바 doc 소 개 를 살 펴 보 았 습 니 다.A container object which may or may not contain a non-null value. If a value is present, isPresent() will return true and get() will return the value.
이것 은 null 값 이 아 닌 용 기 를 포함 하거나 포함 하지 않 을 수 있 는 용기 입 니 다.값 이 존재 하면 isPresent()방법 은 true 를 되 돌려 주 고 get()방법 을 호출 하면 대상 을 되 돌려 줍 니 다.
1.2、진급 해결
우 리 는 getUserById 가 이미 객관 적 으로 존재 하 는 바 꿀 수 없 는 방법 이 라 고 가정 합 니 다.그러면 isPresent 와 get 두 가지 방법 을 이용 하여 우 리 는 지금 아래 의 코드 를 쓸 수 있 습 니 다.
Optional<User> user = Optional.ofNullable(getUserById(id));
if (user.isPresent()) {
String username = user.get().getUsername();
System.out.println("Username is: " + username); // username
}
코드 를 보 는 것 은 좀 아름 다운 것 같 지만,사실 이것 은 이전에 null 값 을 판단 한 코드 와 본질 적 인 차이 가 없 으 며,오히려 optional 로 value 를 봉인 하여 코드 량 을 증가 시 켰 다.그래서 우 리 는 Optional 이 어떤 방법 을 제공 하여 더 좋 은(정확 한 자세 로)Optional 을 사용 할 수 있 는 지 살 펴 보 자.2.optional 세 가지 정적 구조 방법
1)개요:
JDK 는 optional 을 구성 하 는 세 가지 정적 방법 을 제공 합 니 다.
1、Optional.of(T value)
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
이 방법 은 null 이 아 닌 value 를 통 해 optional 을 구성 하고 돌아 오 는 optional 은 value 라 는 값 을 포함 합 니 다.이 방법 에 대해 들 어 오 는 인 자 는 null 이 어야 합 니 다.그렇지 않 으 면 NullPointer Exception 을 던 집 니 다.2、Optional.ofNullable(T value)
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
이 방법 과 of 방법의 차 이 는 들 어 오 는 매개 변 수 는 null-그러나 앞 에 있 는 자바 doc 는 optional 은 비 null 값 만 포함 할 수 있다 고 하지 않 았 습 니까?우 리 는 of Nullable 방법의 소스 코드 를 볼 수 있다.원래 이 방법 은 들 어 오 는 인자 가 null 인지 여 부 를 판단 합 니 다.null 이면 optional.empty()를 되 돌려 줍 니 다.
3、Optional.empty()
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
이 방법 은 빈 optional 을 구성 하 는 데 사 용 됩 니 다.즉,이 optional 에는 값 이 포함 되 어 있 지 않 습 니 다.-사실 바 텀 이 실현 되 는 지,아니면 optional 의 value 가 null 이면 이 optional 은 값 이 포함 되 지 않 은 상태 입 니 다.그리고 API 차원 에서 optional 은 null 값 을 포함 하지 않 고 포함 되 지 않 는 두 가지 상태 만 존재 합 니 다.2)분석:
앞에서 javadoc 에서 도 언급 한 바 와 같이 optional 의 isPresent()방법 은 값 이 포함 되 어 있 는 지,get()은 optional 에 포 함 된 값 을 가 져 오 는 데 사 용 됩 니 다.즉,값 이 존재 하지 않 으 면 optional.empty 에서 get()방법 을 호출 하면 NoSuchElement Exception 이상 을 던 집 니 다.
3)요약:
1)Optional.of(obj):들 어 오 는 obj 는 null 값 이 아 닙 니 다.그렇지 않 으 면 캐릭터 에 들 어가 기 전에 NullPointer Exception 이상 에 쓰 러 집 니 다.
2)optional.of Nullable(obj):스마트 하고 너 그 러 운 방식 으로 optional 인 스 턴 스 를 구성 합 니 다.오 는 사람 이 거절 하지 않 고 null 을 들 어가 면 optional.empty()를 받 습 니 다.null 이 아니면 optional.of(obj)를 호출 합 니 다.
그것 은 우리 가 optional.of Nullable(obj)로 영원히 일 하고 변 하지 않 는 방식 으로 optional 인 스 턴 스 를 구성 하면 되 는 것 입 니까?그렇다 고 꼭 그렇지 는 않 습 니 다.그렇지 않 으 면 optional.of(obj)가 왜 이렇게 노출 되 었 습 니까?개인 적 으로 는 가능 합 니 다.
3.optional 상용 방법 에 대한 상세 한 설명
3.1 옵션 상용 방법 에 대한 개술
Optional.of(T t)
지정 한 값 을 optional 로 봉 한 후 되 돌려 줍 니 다.이 값 이 null 이면 NullPointer Exception 이상 을 던 집 니 다.
Optional.empty()
빈 optional 인 스 턴 스 를 만 듭 니 다.
Optional.ofNullable(T t)
지정 한 값 을 optional 로 밀봉 한 후 되 돌려 줍 니 다.이 값 이 null 이면 빈 optional 대상 을 되 돌려 줍 니 다.
isPresent
값 이 true 로 돌아 가 는 것 이 있 으 면 false 로 돌아 갑 니 다.
ifPresent
optional 인 스 턴 스 가 값 이 있 으 면 consumer 를 호출 합 니 다.그렇지 않 으 면 처리 하지 않 습 니 다.
ifPresent 방법 을 이해 하려 면 먼저 Consumer 류 를 알 아야 합 니 다.간단하게 말 하면 Consumer 류 는 추상 적 인 방법 을 포함한다.이 추상 적 인 방법 은 들 어 오 는 값 을 처리 하지만 되 돌아 오지 않 았 다.자바 8 은 인터페이스 없 이 lambda 표현 식 을 통 해 인 자 를 직접 전달 하 는 것 을 지원 합 니 다.
optional 인 스 턴 스 가 값 이 있 으 면 ifPresent()를 호출 하면 인터페이스 세그먼트 나 lambda 표현 식 을 받 아들 일 수 있 습 니 다.
Optional.get()
이 값 이 존재 한다 면 이 값 을 optional 패키지 로 되 돌려 줍 니 다.그렇지 않 으 면 NoSuchElement Exception 이상 을 던 집 니 다.
orElse(T t)
호출 대상 에 값 이 포함 되 어 있 으 면 이 값 을 되 돌려 줍 니 다.그렇지 않 으 면 t 를 되 돌려 줍 니 다.
orElseGet(Supplier s)
호출 대상 이 값 을 포함 하면 이 값 을 되 돌려 줍 니 다.그렇지 않 으 면 s 가 가 져 온 값 을 되 돌려 줍 니 다.
orElseThrow()
그것 은 대상 이 비어 있 을 때 이상 을 던 질 것 이다.
map(Function f)
값 이 존재 하면 이 값 에 제 공 된 mapping 함수 호출 을 실행 합 니 다.
flatMap(Function mapper)
값 이 존재 하면 이 값 에 제 공 된 mapping 함수 호출 을 실행 하고 optional 형식의 값 을 되 돌려 줍 니 다.그렇지 않 으 면 빈 optional 대상 을 되 돌려 줍 니 다.
3.2 Optional 상용 방법 에 대한 상세 한 설명
3.2.1、ifPresent
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
만약 optional 에 값 이 있다 면,이 값 에 대해 consumer.accept 를 호출 합 니 다.그렇지 않 으 면 아무것도 하지 않 습 니 다.그래서 머리말 의 예 에 대해 우 리 는 다음 과 같이 수정 할 수 있다.
Optional<User> user = Optional.ofNullable(getUserById(id));
user.ifPresent(u -> System.out.println("Username is: " + u.getUsername()));
3.2.2、orElse
public T orElse(T other) {
return value != null ? value : other;
}
optional 에 값 이 있 으 면 되 돌려 줍 니 다.그렇지 않 으 면 orElse 방법 으로 들 어 온 인 자 를 되 돌려 줍 니 다.
User user = Optional
.ofNullable(getUserById(id))
.orElse(new User(0, "Unknown"));
System.out.println("Username is: " + user.getUsername());
3.2.3、orElseGet
public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
}
orElseGet 과 orElse 방법의 차 이 는 orElseGet 방법 이 들 어 오 는 매개 변 수 는 하나의 Supplier 인터페이스의 실현-optional 에 값 이 있 을 때 값 을 되 돌려 주 는 것 이다.optional 에 값 이 없 을 때 이 Supplier 에서 얻 은 값 을 되 돌려 줍 니 다.
User user = Optional
.ofNullable(getUserById(id))
.orElseGet(() -> new User(0, "Unknown"));
System.out.println("Username is: " + user.getUsername());
3.2.4、orElseThrow
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}
orElseThrow 와 orElse 방법의 차 이 는 orElseThrow 방법 이 optional 에 값 이 있 을 때 값 을 되 돌려 주 는 것 이다.값 이 없 을 때 이상 을 던 지고 이상 을 던 지 는 것 은 들 어 오 는 exception Supplier 에서 제공 합 니 다.예 를 들 어 설명:
SpringMVC 컨트롤 러 에 서 는 여러 가지 이상 을 통일 적 으로 처리 할 수 있 습 니 다.어떤 실 체 를 조회 할 때 데이터베이스 에 해당 하 는 기록 이 있 으 면 이 기록 을 되 돌려 줍 니 다.그렇지 않 으 면 Entity NotFoundException 을 던 져 서 Entity NotFoundException 을 처리 하 는 방법 에서 저 희 는 클 라 이언 트 에 게 Http 상태 코드 404 와 이상 하 게 대응 하 는 정 보 를 되 돌려 줍 니 다.orElseThrow 는 이런 장면 에 완벽 하 게 적 용 됩 니 다.
@RequestMapping("/{id}")
public User getUser(@PathVariable Integer id) {
Optional<User> user = userService.getUserById(id);
return user.orElseThrow(() -> new EntityNotFoundException("id " + id + " "));
}
@ExceptionHandler(EntityNotFoundException.class)
public ResponseEntity<String> handleException(EntityNotFoundException ex) {
return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND);
}
3.2.5、map
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Optional.ofNullable(mapper.apply(value));
}
}
현재 optional 이 optional.empty 이면 optional.empty 로 돌아 갑 니 다.그렇지 않 으 면 새로운 optional 을 되 돌려 줍 니 다.이 optional 은 함수 mapper 가 value 를 입력 할 때의 출력 값 을 포함 합 니 다.
String username = Optional.ofNullable(getUserById(id))
.map(user -> user.getUsername())
.orElse("Unknown")
.ifPresent(name -> System.out.println("Username is: " + name));
그리고 우 리 는 맵 조작 을 여러 번 사용 할 수 있다.
Optional<String> username = Optional.ofNullable(getUserById(id))
.map(user -> user.getUsername())
.map(name -> name.toLowerCase())
.map(name -> name.replace('_', ' '))
.orElse("Unknown")
.ifPresent(name -> System.out.println("Username is: " + name));
3.2.6、flatMap
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Objects.requireNonNull(mapper.apply(value));
}
}
flatMap 방법 과 map 방법의 차 이 는 map 방법 매개 변수 중의 함수 mapper 가 값 을 출력 한 다음 에 map 방법 은 optional.of Nullable 을 사용 하여 이 를 optional 로 포장 합 니 다.flatMap 은 매개 변수 중의 함수 mapper 출력 을 요구 하 는 것 이 바로 optional 입 니 다.
Optional<String> username = Optional.ofNullable(getUserById(id))
.flatMap(user -> Optional.of(user.getUsername()))
.flatMap(name -> Optional.of(name.toLowerCase()))
.orElse("Unknown")
.ifPresent(name -> System.out.println("Username is: " + name));
3.2.7、filter
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
filter 방법 은 Predicate 를 받 아들 여 optional 에 포 함 된 값 을 걸 러 냅 니 다.포 함 된 값 이 조건 에 만족 하면 이 optional 을 되 돌려 줍 니 다.그렇지 않 으 면 optional.empty 로 돌아 갑 니 다.
Optional<String> username = Optional.ofNullable(getUserById(id))
.filter(user -> user.getId() < 10)
.map(user -> user.getUsername());
.orElse("Unknown")
.ifPresent(name -> System.out.println("Username is: " + name));
4.옵션 사용 예시4.1 사용 전시 1
user.is Present()가 진실 이 고 관련 된 orders 의 맵 집합 을 얻 을 수 있 습 니 다.가짜 로 빈 집합 으로 돌아 갈 때 우 리 는 위의 orElse,orElseGet 방법 이 모두 힘 이 없 을 때 그것 은 원래 map 함수 의 책임 입 니 다.우 리 는 이렇게 할 수 있 습 니 다.
return user.map(u -> u.getOrders()).orElse(Collections.emptyList())
// Java 8
if(user.isPresent()) {
return user.get().getOrders();
} else {
return Collections.emptyList();
}
map 는 무한 연결 이 가능 합 니 다.예 를 들 어 한 층 더 깊이 들 어가 사용자 이름 을 얻 는 대문자 형식 입 니 다.
return user.map(u -> u.getUsername())
.map(name -> name.toUpperCase())
.orElse(null);
이전의 방법:
User user = .....
if(user != null) {
String name = user.getUsername();
if(name != null) {
return name.toUpperCase();
} else {
return null;
}
} else {
return null;
}
filter():값 이 있 고 조건 을 만족 시 키 면 이 값 을 포함 하 는 optional 을 되 돌려 줍 니 다.그렇지 않 으 면 빈 optional 을 되 돌려 줍 니 다.
Optional<String> longName = name.filter((value) -> value.length() > 6);
System.out.println(longName.orElse("The name is less than 6 characters"));
총결산이상 은 이 글 의 모든 내용 입 니 다.본 고의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가 치 를 가지 기 를 바 랍 니 다.여러분 의 저희 에 대한 지지 에 감 사 드 립 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
【Liquibase】DB 작성·테이블 정의 변경신규 스타터 프로젝트 작성 Liquibase와 MySQL 선택 application.properties에 DB 정보 넣기 MySQL에서 "testdatabase"라는 데이터베이스 만들기 빌드 종속성 추가 build....
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.