Java에서 빈 포인터 이상을 방지하는 방법
본고는 다음과 같은 몇 가지 기술을 토론할 것이다
1.Optional 유형(Java 8에 새로 도입된)
2. Objects 클래스(Java 7 중원에 있음)
Java 8의 Optional 클래스
그것은 무엇입니까?
1.Java 8에 새로 도입된 유형
2. 이것은 특정한 유형의 대상의 포장기나 존재하지 않는 대상(null)의 장면에 사용된다
간단하게 말하자면, 그것은 빈 값을 처리하는 더 좋은 대체품이다. (경고: 언뜻 보기에는 그렇게 뚜렷하지 않을 수도 있다)
기본용법
그것은 하나의 유형 (한 종류) 이다. 그러면 어떻게 해야만 이 유형의 실례를 만들 수 있습니까?
그것의 세 가지 정적 방법을 사용하면 된다.
public static Optional<String> stringOptional(String input) {
return Optional.of(input);
}
간단명료합니다. 이 값을 포함하는 Optional 패키지를 만듭니다.기억해라. 만약 이 값이null이라면 NPE를 던질 것이다!
public static Optional<String> stringNullableOptional(String input) {
if (!new Random().nextBoolean()) {
input = null;
}
return Optional.ofNullable(input);
}
나는 개인적으로 좀 더 좋아야 한다고 생각한다.이렇게 하면 NPE의 위험이 없다. null로 입력하면 빈 Optional로 되돌아온다.
public static Optional<String> emptyOptional() {
return Optional.empty();
}
만약 당신이 정말로 빈 값을 되돌려 주기를 원한다면, 빈 값은 null을 의미하지 않습니다.알겠습니다. 그럼 어떻게 Optional을 소비/사용합니까?
public static void consumingOptional() {
Optional<String> wrapped = Optional.of("aString");
if (wrapped.isPresent()) {
System.out.println("Got string - " + wrapped.get());
}
else {
System.out.println("Gotcha !");
}
}
간단한 방법은 Optional 패키지가 정말 가치가 있는지 확인하는 것이다. (isPresent 방법을 사용하면) 이것은 if(myObj!=null)를 사용하는 것보다 무엇이 좋은지 의심할 것이다.걱정 마, 그건 내가 분명히 설명할게.
public static void consumingNullableOptional() {
String input = null;
if (new Random().nextBoolean()) {
input = "iCanBeNull";
}
Optional<String> wrapped = Optional.ofNullable(input);
System.out.println(wrapped.orElse("default"));
}
만약에 봉인된null값이 확실하다면 기본값을 되돌려 줄 수 있는 orElse 방법을 사용할 수 있습니다.실제 값을 추출할 때 ifPresent 방법을 사용하는 것을 피할 수 있습니다.
public static void consumingEmptyOptional() {
String input = null;
if (new Random().nextBoolean()) {
input = "iCanBeNull";
}
Optional<String> wrapped = Optional.ofNullable(input);
System.out.println(wrapped.orElseGet(
() -> {
return "defaultBySupplier";
}
));
}
그건 좀 모르겠어요.왜 같은 목적의 다른 두 가지 방법이 있습니까?orElse와 orElseGet은 분명히 다시 불러올 수 있습니다(같은 이름이지만 다른 매개 변수).어쨌든, 이 두 가지 방법의 뚜렷한 차이는 바로 그들의 매개 변수에 있다. - 당신은 Supplier의 실례가 아닌 lambda 표현식을 사용하여 이것을 완성할 수 있다.
왜 Optional을 사용하는 것이 흔한 null 검사보다 낫습니까?
1. Optional을 사용하는 가장 큰 장점은 당신의 의도를 더욱 명확하게 표현할 수 있다는 것이다. null값을 되돌리면 소비자들이 의심하게 할 수 있기 때문에 (실제로 NPE가 나타날 때) 일부러 되돌린 것이 아닌지 의심스러워하기 때문에javadoc를 확인해서 더 포지셔닝해야 한다.Optional을 사용하면 상당히 명확합니다.
2. Optional이 있으면 NPE를 철저히 피할 수 있다. 위에서 언급한 바와 같이 Optional을 사용한다.ofNullable, orElse 및 orElseGet은 NPE를 멀리할 수 있습니다.
또 다른 구원의 별!
이 코드 세션 보세요.
package com.abhirockzz.wordpress.npesaviors;
import java.util.Map;
import java.util.Objects;
public class UsingObjects {
String getVal(Map<String, String> aMap, String key) {
return aMap.containsKey(key) ? aMap.get(key) : null;
}
public static void main(String[] args) {
UsingObjects obj = new UsingObjects();
obj.getVal(null, "dummy");
}
}
어느 것이 비어 있을 수 있습니까?1. Map 객체
2. 검색에 사용되는 키
3. 방법 호출의 이 실례
만약 NPE를 던진다면, 우리는 도대체 어느 것이null인지 어떻게 확정할 수 있습니까?
package com.abhirockzz.wordpress.npesaviors;
import java.util.Map;
import java.util.Objects;
public class UsingObjects {
String getValSafe(Map<String, String> aMap, String key) {
Map<String, String> safeMap = Objects.requireNonNull(aMap,
"Map is null");
String safeKey = Objects.requireNonNull(key, "Key is null");
return safeMap.containsKey(safeKey) ? safeMap.get(safeKey) : null;
}
public static void main(String[] args) {
UsingObjects obj = new UsingObjects();
obj.getValSafe(null, "dummy");
}
}
requireNonNull 방법1. 대상이 null이 아니라면 그 자체로 돌아가기
2. 값이 null이면 반환된 NPE에 지정된 메시지가 표시됩니다.
왜 if(my Obj!=null)보다 좋아요?
당신이 본 창고 추적 정보는 Objects를 똑똑히 볼 수 있습니다.requireNonNull 메서드를 호출합니다.이것은 다시 당신의 오류 로그에 맞추면 문제를 더 빨리 포지셔닝할 수 있습니다...적어도 내가 보기엔 더 빨라.
예를 들어 간단한 검사기를 실현하여 빈 값이 없도록 할 수도 있다.
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;
public class RandomGist {
public static <T> T requireNonEmpty(T object, Predicate<T> predicate, String msgToCaller){
Objects.requireNonNull(object);
Objects.requireNonNull(predicate);
if (predicate.test(object)){
throw new IllegalArgumentException(msgToCaller);
}
return object;
}
public static void main(String[] args) {
//Usage 1: an empty string (intentional)
String s = "";
System.out.println(requireNonEmpty(Objects.requireNonNull(s), (s1) -> s1.isEmpty() , "My String is Empty!"));
//Usage 2: an empty List (intentional)
List list = Collections.emptyList();
System.out.println(requireNonEmpty(Objects.requireNonNull(list), (l) -> l.isEmpty(), "List is Empty!").size());
//Usage 3: an empty User (intentional)
User user = new User("");
System.out.println(requireNonEmpty(Objects.requireNonNull(user), (u) -> u.getName().isEmpty(), "User is Empty!"));
}
private static class User {
private String name;
public User(String name){
this.name = name;
}
public String getName(){
return name;
}
}
}
NPE가 잘못된 곳에서 고통이 되지 않도록 하세요.우리는 NPE를 더욱 잘 처리하고 심지어는 철저히 근절할 수 있는 많은 도구가 있다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.