각각 다르게 정의하고 있지만 큰 부류로
¹ String str = ""; 와 같이 “빈 값”이 객체에 할당되어 있기 때문에 null과는 다르며,
² 0도 0이라는 값이 할당된 상태이기 때문에 null과는 전혀 다르다.
NullPointer
문제가 150여 개 발생-> 그만큼 null과 관련된 Exception
이나 오류가 많이 흔히 발생하고 있다는 뜻
@NonNullApi
애너테이션을 선언하면 패키지 하위의 class method의 인자 또는 리턴이 null일 경우 IDE에서 Warning으로 알려준다. /**
* 이렇게 사용하지 말고
*/
private void wrongWay() {
User user = null;
}
/**
* 이렇게 사용하세요.
*/
private void correctWay() {
User user = new User();
}
/**
* 사용 ㄴㄴ
*/
private User getUser(int userId) {
return userRepository.findById(userId).orElse(null);
}
/**
* 이렇게 사용하세요.
*/
private Optional<User> getUser(int userId) {
return userRepository.findById(userId);
}
/**
* 이렇게도 사용해보자
*/
private UserResponse getUserInfo(int userId) {
UserResponse response = UserResponse.builder().build();
int userId = 1;
Optional<User> optionalUser = getUser(userId); //Optional
optionalUser.ifPresent(response::setUser);
return response;
}
//빈 객체로 리턴해주자
private User getUser(int userId) {
return userRepository
.findById(userId)
.orElseGet(() -> User.builder().build());
}
/**
* 이렇게 사용하지 마시고.
*/
private User getUserName(int userId) {
User user = getUser(userId);
if (Objects.isNull(user)) {
throw new IllegalArgumentException("사용자를 찾을 수 없습니다.");
}
return user.getName();
}
/**
* 이렇게도 사용하지 마시고.
*/
private User getUserName(int userId) {
Optional<User> user = getUser(userId);
boolean present = user.isPresent();
if (!present) {
throw new IllegalArgumentException("사용자를 찾을 수 없습니다.");
}
return user.getName();
}
/**
* 이렇게 사용하세요.
*/
private User getUserName(int userId) {
User user = getUser(userId);
String userName = user.getName();
if (userName == null) {
throw new IllegalArgumentException("사용자를 찾을 수 없습니다.");
}
return user.getName();
}
이렇게 null인 경우 예외로 던져주자
API에 null을 최대한 쓰지 말아라
Objects.requireNonNull()
을 사용하여 방어하자사전 조건과 사후 조건을 확인하라: “계약에 의한 설계”
(상태와 같이) null의 범위를 지역(클랫, 메서드)에 제한하라
초기화를 명확히 하라
eastglow 님의 글을 참조하여 작성하였습니다.
webgori 님의 글을 참조하여 작성하였습니다.