Java에서 선택적 옵션을 사용하여 빈 포인터 예외 방지
14333 단어 programmingjava
1964년에 영국 컴퓨터 과학자 토니 홀은 공지침 인용을 발명했다.
빈 지침 이상은 생산 이상에서 가장 흔히 볼 수 있는 오류다.그것은 C, C++, C#, 자바스크립트, 자바 등을 포함한 많은 프로그래밍 언어로 이루어졌다.
홀은 그에 필요한 재력, 시간, 인적 자원 손실을 복구하여 이를 'a' billion-dollar mistake 라고 불렀다.
Java는 빈 포인터 참조를 구현하는 프로그래밍 언어 중 하나입니다.만약 네가 줄곧 자바로 개발하고 있다면, 나는 네가 이미 많은 것을 보았다고 믿는다.자네가 자바 초보든 10년의 경험이 있든항상 빈 포인터 오류가 발생할 수 있습니다.
Java 옵션
Optional
는 Java 8에 도입된 API입니다.만약 적절하게 사용한다면, 그것은 빈 바늘의 이상한 문제를 해결할 수 있을 것이다.옵션 API는 함수를 프로그래밍하고 함수 인터페이스를 사용합니다.
자바 함수식 프로그래밍에 대한 지식을 더 알고 싶으면, 제 다른 글 Functional Programming in Java, Explained 을 읽어 주십시오.
계속하기 전에 이 문서의 예는 Java11을 사용합니다.다른 버전의 Java를 사용하는 경우 일부 메서드가 존재하지 않거나 동작이 동일할 수 있습니다.
빈 옵션
optional
API를 사용할 때 비어 있는 Optional
는 빈 바늘의 이상을 피하는 주요한 방법이다.Optional
의 흐름에서null은 공백Optional
으로 전환됩니다.비어 있는 Optional
는 더 이상 처리되지 않습니다.이것이 바로 우리가 NullPointerException
를 사용할 때 Optional
를 피하는 방법이다.우리는 본문 뒤에 공
Optional
의 행위를 더욱 이해할 것이다.선택적 객체 만들기
객체를 시작할 수 있는 세 가지 방법이 있습니다
Optional
.Optional.of(T)
Optional.ofNullable(T)
Optional.empty()
선택할 수 있습니다.... 에 속하다
Optional.of
매개변수 중 빈 값이 될 수 없는 유형을 적용합니다.Optional
를 사용하여 Optional.of
대상을 만들려면 매개 변수에 값을 전달해야 합니다. @Test
public void initializeOptional_optionalOf() {
Optional<String> helloWorldOptional = Optional.of("Hello, world");
assert helloWorldOptional.isPresent();
assert "Hello, world".equals(helloWorldOptional.get());
}
값을 Optional.of
에 전달할 때는 매우 조심해야 한다.Optional.of
는 매개변수의 빈 값을 허용하지 않습니다.빈 값을 전달하려고 하면 NullPointerException
을 생성합니다. @Test
public void initializeOptional_optionalOf_null() {
try {
Optional.of(null);
} catch (Exception e) {
assert e instanceof NullPointerException;
}
}
선택할 수 있습니다.남에게 말할 수 없었어
Optional.ofNullable
는 옵션과 유사합니다.그럼요.그것은 모든 종류를 받아들일 수 있다.다른 점은 Optional.ofNullable
를 사용하면 빈 값을 매개 변수에 전달할 수 있다는 것이다. @Test
public void initializeOptional_optionalOfNullable() {
Optional<String> helloWorldOptional = Optional.ofNullable("Hello, world");
assert helloWorldOptional.isPresent();
assert "Hello, world".equals(helloWorldOptional.get());
}
빈 대상을 초기화할 때 Optional.ofNullable
빈 대상을 되돌려줍니다. @Test
public void initializeOptional_optionalOfNullable_null() {
Optional<String> helloWorldOptional = Optional.ofNullable(null);
assert !helloWorldOptional.isPresent();
try {
helloWorldOptional.get();
} catch (Exception e) {
assert e instanceof NoSuchElementException;
}
}
선택할 수 있습니다.텅 비었어
Optional
를 사용하여 공백Optional
을 초기화할 수 있습니다. @Test
public void initializeOptional_optionalEmpty() {
Optional<String> helloWorldOptional = Optional.empty();
assert !helloWorldOptional.isPresent();
}
액세스 옵션
Optional 의 값을 가져올 수 있는 몇 가지 방법이 있습니다.
얻다
이것은 매우 간단한 방법이다.
Optional.empty()
방법이 존재하면 get
의 값을 되돌려주고 이 값이 존재하지 않으면 던진다Optional
. @Test
public void get_test() {
Optional<String> helloWorldOptional = Optional.of("Hello, World");
assert "Hello, World".equals(helloWorldOptional.get());
}
@Test
public void get_null_test() {
Optional<String> helloWorldOptional = Optional.empty();
try {
helloWorldOptional.get();
} catch (Exception e) {
assert e instanceof NoSuchElementException;
}
}
오레르스
NoSuchElementException
가 비어 있을 때 기본값을 사용하려면 Optional
방법을 사용할 수 있습니다. @Test
public void orElse_test() {
Optional<String> helloWorldOptional = Optional.of("Hello, World");
assert "Hello, World".equals(helloWorldOptional.orElse("default"));
}
@Test
public void orELseNull_test() {
Optional<String> helloWorldOptional = Optional.empty();
assert "default".equals(helloWorldOptional.orElse("default"));
}
올레스게이트
orElse
와 orElseGet
방법은 매우 비슷하다.다만 orElse
그것을 매개 변수로 받아들인다. @Test
public void orElseGet_test() {
Optional<String> helloWorldOptional = Optional.of("Hello, World");
assert "Hello, World".equals(helloWorldOptional.orElseGet(() ->"default"));
}
@Test
public void orELseGet_Null_test() {
Optional<String> helloWorldOptional = Optional.empty();
assert "default".equals(helloWorldOptional.orElseGet(() ->"default"));
}
오레슬리
orElseGet
는 Supplier<T>
의 값을 되돌려주거나 orElseThrow
의 값이 비어 있을 때 이상을 일으킨다. @Test
public void orElseThrow_test() {
Optional<String> helloWorldOptional = Optional.of("Hello, World");
assert "Hello, World".equals(helloWorldOptional.orElseThrow(NullPointerException::new));
}
@Test
public void orELseThrow_Null_test() {
Optional<String> helloWorldOptional = Optional.empty();
try {
helloWorldOptional.orElseThrow(NullPointerException::new);
} catch (Exception e) {
assert e instanceof NullPointerException;
}
}
옵션 처리
처리하고 전환할 수 있는 방법이 많다
Optional
.이 절에서 우리는 자주 사용하는 방법을 배울 것이다.내가 본문 첫머리에 쓴 바와 같이 흐름 중에는 빈 것을 처리하지 않는다
Optional
.우리는 이 절의 예시에서 이 점을 볼 수 있다.지도.
Optional
는 Optional
대상을 처리할 때 가장 자주 사용하는 방법이다.이것은 map
매개 변수로 받아들여지고 Optional
되돌아옵니다. 이것은 함수를 모든 종류의 매개 변수와 함께 사용할 수 있음을 의미합니다. 되돌아오는 값은 Function<? super T, ? extends U>
방법에서 Optional<U>.
로 포장됩니다. @Test
public void processingOptional_map_test() {
Optional<String> stringOptional = Optional.of("Hello, World")
.map(a -> a + ", Hello");
assert stringOptional.isPresent();
assert "Hello, World, Hello".equals(stringOptional.get());
}
Optional
에서 빈 값을 되돌려 보려고 시도하면 map
방법은 빈 값Function<? super T, ? extends U>
을 되돌려 줍니다. @Test
public void processingOptional_map_empty_test() {
Optional<String> stringOptional = Optional.of("Hello, World")
.map(a -> null);
assert !stringOptional.isPresent();
}
map
빈 옵션은 처리되지 않습니다.다음과 같은 테스트를 통해 이를 확인할 수 있습니다. @Test
public void processingOptional_map_empty_notProcessed_test() {
AtomicBoolean atomicBoolean = new AtomicBoolean(false);
Optional<String> stringOptional = Optional.of("Hello, World")
.map(a -> null)
.map(a -> {
atomicBoolean.set(true);
return "won't be processed";
});
assert !stringOptional.isPresent();
assert atomicBoolean.get() == false;
}
평면도
이것은
Optional
와 유사하지만 map
는 함수의 반환값을 map
로 포장하지 않습니다.flatMap
방법은 Optional
를 매개 변수로 받아들인다.이것은 어떤 종류를 받아들이고 flatMap
되돌아오는 함수를 정의해야 한다는 것을 의미합니다.코드가 다른 반환
Function<? super T, ? extends Optional<? extends U>>
대상의 방법을 호출할 때, 보통 Optional
방법을 사용합니다.
@Test
public void processingOptional_flatmap_test() {
Optional<String> stringOptional = Optional.of("Hello, World")
.flatMap(this::getString);
assert "Hello, World, Hello".equals(stringOptional.get());
}
@Test
public void processingOptional_flatmap_randomString_test() {
Optional<String> stringOptional = Optional.of(UUID.randomUUID().toString())
.flatMap(this::getString);
assert !stringOptional.isPresent();
}
public Optional<String> getString(String s) {
if ("Hello, World".equals(s)) {
return Optional.of("Hello, World, Hello");
}
return Optional.empty();
}
필터
flatMap
의 이전 예에서 우리는 성명식 양식을 사용하여 Optional
방법의 반환 값을 구분한다.그러나 우리는 실제로 flatMap
방법을 사용하여 이 점을 실현할 수 있다. @Test
public void processingOptional_filter_test() {
Optional<String> stringOptional = Optional.of("Hello, World")
.filter(helloWorldString -> "Hello, World".equals(helloWorldString))
.map(helloWorldString -> helloWorldString + ", Hello");
assert "Hello, World, Hello".equals(stringOptional.get());
}
@Test
public void processingOptional_filter_randomString_test() {
Optional<String> stringOptional = Optional.of(UUID.randomUUID().toString())
.filter(helloWorldString -> "Hello, World".equals(helloWorldString))
.map(helloWorldString -> helloWorldString + ", Hello");
assert !stringOptional.isPresent();
}
view rawProcessingOptionalT
하면, 만약, 만약...
getString
방법은 하나filter
를 받아들여 옵션이 비어 있지 않을 때만 실행됩니다. @Test
public void processingOptional_ifPresent_test() {
AtomicBoolean atomicBoolean = new AtomicBoolean(false);
Optional.of("Hello, World")
.ifPresent(helloWorldString -> atomicBoolean.set(true));
assert atomicBoolean.get();
}
@Test
public void processingOptional_ifPresent_empty_test() {
AtomicBoolean atomicBoolean = new AtomicBoolean(false);
Optional.empty()
.ifPresent(helloWorldString -> atomicBoolean.set(true));
assert !atomicBoolean.get();
}
모면할 일
코드
ifPresent
에서 사용하려면 중요한 일을 피해야 한다.옵션 적용 방법을 만들지 마십시오.
매개 변수로 받아들이는 방법을 만들면 해결하고자 하는 문제를 도입할 수 있습니다.
Consumer
만약 Optional
파라미터를 가진 방법을 사용하는 사람이 그것을 모른다면, 그들은 Optional
대신 null을 이 방법에 전달할 수 있다.처리 aNullPointerException
는 aOptional
를 생성한다. @Test
public void optionalAsParameter_test() {
try {
isPhoneNumberPresent(null);
} catch (Exception e) {
assert e instanceof NullPointerException;
}
}
public boolean isPhoneNumberPresent(Optional<String> phoneNumber) {
return phoneNumber.isPresent();
}
검사 없이 가치 실현
Optional.empty()
를 사용하고 있다면 get 방법을 사용하지 마십시오.만약 어떤 이유로 그것을 사용해야 한다면, 우선 null
방법으로 검사를 진행하십시오. 비어 있는 NullPointerException
에서 get을 사용하면 Optional
생성되기 때문입니다. @Test
public void getWithIsPresent_test() {
Optional<String> helloWorldOptional = Optional.ofNullable(null);
if (helloWorldOptional.isPresent()) {
System.out.println(helloWorldOptional.get());
}
}
@Test
public void getWithoutIsPresent_error_test() {
Optional<String> helloWorldOptional = Optional.ofNullable(null);
try {
System.out.println(helloWorldOptional.get());
} catch (Exception e) {
assert e instanceof NoSuchElementException;
}
}
결론
끝까지 읽어주셔서 감사합니다!옵션 기능은 모든 Java 개발자가 알아야 할 강력한 기능입니다.만약 당신이 정확하게 한쪽에서 다른 한쪽으로 선택할 수 있는 기능을 사용한다면, 나는 당신이 더 이상
isPresent
의 요구를 만족시키지 못할 것이라고 믿습니다.Optional은 다른 대형 라이브러리(예를 들어 Reactor와 RXJava)의 기초로도 사용되기 때문에 Optional의 작업 원리를 이해하는 것도 이를 이해하는 데 도움이 될 것입니다.
이 문서의 예제에서 저장소를 찾을 수 있습니다.
https://github.com/brilianfird/java-optional
도구책
Reference
이 문제에 관하여(Java에서 선택적 옵션을 사용하여 빈 포인터 예외 방지), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/brilianfird/avoiding-the-null-pointer-exception-with-optional-in-java-224i텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)