22년 09월 03일에 작성된 글
Optional
Optional
객체 생성
/*
str(100번지) -> "abc"(100번지 값)
optVal(200번지) -> 100번지 주소(200번지 값) -> "abc"(100번지 값)
이렇게 참조하고 있다.
*/
String str = "abc"
Optional<String> optVal = Optional.of(str);
Optional<String> optVal2 = Optional.of(null); // 널포인터 익셉션 오류 발생 Null을 다루기 위해 Optional을 쓰기때문에 이건 잘 안씀
Optional<String> optVal3 = Optional.ofNullable(null); // 오류 안남
Optional<String> optVal = null; // 바람직하지 않음
Optional<String> optVal = Optional.empty(); // 빈 객체로 초기화
Optional
객체 값 가져오기
Optional<String> optVal = Optional.of("abc");
String str1 = optVal.get(); // optVal에 저장된 값 반환. null이면 예외 발생
//이 아래것들을 자주 씀
String str2 = optVal.orElse(""); // optVal에 저장된 값이 null이면 ""를 반환
String str3 = optVal.orElseGet(String::new); // 람다식 사용가능, optVal에 저장된 값이 null이면 new String()를 반환
String str4 = optVal.orElseThrow(NullPointerException::new); //널이면 예외 발생
//orElse와 orElseGet은 같은 것 같지만 다르다. 차이는 아래서 설명한다.
Optional
에서 사용하는 map()
은 Stream
과 똑같이 사용하면 된다.
내용출처: https://www.youtube.com/watch?v=W_kPjiTF9RI
Optional.orElse()
VS Optional.orElseGet()
orElse()
는 null과 상관없이 항상 불립니다. orElseGet()
은 null일 때만 불린다. 다음 예시를 통해 위험한 상황을 확인하자.
public User findByUsername(String name) {
return userRepository.findByName(name).orElse(createUserWithName(name));
}
private User createUserWithName(String name) {
User newUser = new User();
newUser.setName(name)
return userRepository.save(user);
}
위의 상황은 orElse()
로 인해 createUserWithName()
메소드가 User
가 null이든 말든 실행된다. 그러므로 항상 User
가 생성되는 상황이다. 만약 name
이 unique였다면 장애가 발생하는 상황이다.
즉 위 코드는 아래코드와 같다.
public User findByUsername(String name) {
User newUser = createUserWithName(name); // 무조건 User를 생성해서 DB에 저장
return userRepository.findByName(name).orElse(newUser);
}
private User createUserWithName(String name) {
User newUser = new User();
newUser.setName(name)
return userRepository.save(user);
}
차이를 이해하고 있자
내용 출처: https://cfdf.tistory.com/34