기술나눔

Java의 Optional을 이해하는 하나의 기사

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

1. Optional 소개

Optional은 java8에 도입된 새로운 클래스입니다. 이 클래스가 해결하는 주요 문제는 NullPointerException입니다.
원본 텍스트 번역(Baidu 번역, 영어로 된 내 단점): null이 아닌 값을 포함할 수도 있고 포함하지 않을 수도 있는 컨테이너 개체입니다. isPresent()는 값이 있으면 true를 반환합니다. 값이 없으면 객체는 비어 있는 것으로 간주되고 isPresent()는 false를 반환합니다.
orElse()(값이 없으면 기본값 반환) 및 ifPresent()(값이 있으면 작업 수행)와 같이 포함된 값의 존재 여부에 따라 달라지는 추가 메서드가 제공됩니다.
이는 값 기반 클래스입니다. 프로그래머는 동일한 인스턴스를 교환 가능한 것으로 처리해야 하며 동기화를 위해 인스턴스를 사용해서는 안 됩니다. 그렇지 않으면 예측할 수 없는 동작이 발생할 수 있습니다. 예를 들어, 향후 릴리스에서는 동기화가 실패할 수 있습니다.

여기서 제가 이해하는 핵심 기능은 다음을 통과할 수 있다는 것입니다. isPresent() 물체의 비어 있음을 판단하는 데 도움을 주고 통과시키는 방법map(), orElse()ifPresent() 다른 방법을 조합하면 코드 판단 시간을 크게 줄일 수 있습니다.

2. 일반적으로 사용되는 인터페이스

先介绍一下常用所有的接口;
注意:
	1. 此列表是列出了本人觉得有意义的接口不是全部。
	2. 当前jdk版本为17,其他版本可能会没有一些方法,例如:`or()` 方法在jdk1.9中增加的
  • 1
  • 2
  • 3
  • 4
인터페이스 이름기능에 대한 간략한 설명
Optional<T> empty()비어 있는 구성Optional 물체
Optional<T> of(T value)비어 있지 않은 구성Optional 만약에 반대한다면为空则报错
Optional<T> ofNullable(T value)빌드Optional 객체는 비워둘 수 있습니다!
T get()값이 다음과 같은 경우 일반 개체 값을 가져옵니다.为空,则报错
boolean isPresent()없으면 비어 있음null 그렇다면 그것은true
boolean isEmpty()비어 있는 경우null 그렇다면 그것은true
ifPresent(Consumer)데이터가 있을 때 인터페이스 함수 쌍을 전달합니다.不为空이 기능은 다음과 같은 경우에 실행됩니다.
ifPresentOrElse(Consumer, Runnable) 두 개의 매개변수, 첫 번째 매개변수는 비어 있지 않을 때 실행되고, 두 번째 매개변수는 비어 있을 때 실행됩니다. 모두 인터페이스 기능입니다.
Optional<T> filter객체에 대한 필터
Optional<U> map(Function)변환 방법
Optional<U> flatMap(Function)다중 레이어를 하나의 레이어로 변환하는 데 일반적으로 사용되는 변환 방법
Optional<T> or(Supplier)물건을 받을 때为空인터페이스 기능을 기반으로 새로 생성하는 경우Optional물체
T orElse(T)물건을 받을 때为空다음과 같은 경우 지정된 일반 객체를 가져옵니다.
T orElseThrow()不为空 반환 개체,为空 하지만NoSuchElementException
T orElseThrow(Supplier)不为空 반환 개체,为空 하지만指定异常

2.1 공통 인터페이스는 사용하기 쉽습니다

下面是常用接口的一些简单的演示
  • 1

2.1.1 일반적인 생성 방법

// 1. 构建一个空的 Optional 对象没有任何问题
Optional<Object> empty = Optional.empty();

 // 2. 构建一个非空的 Optional 对象没有任何问题
 Optional<Object> aa = Optional.of("123");
 // 3. 构建一个空的 Optional 对象直接报错  ================ 会报错 of不允许为空
 Optional<Object> bb = Optional.of(null);

 // 4. 构建一个空的 Optional 对象没有任何问题
 Optional<Object> cc = Optional.ofNullable(null);

 // 5. 构建一个非空的 Optional 对象没有任何问题
 Optional<Object> dd = Optional.ofNullable("123");

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

2.1.2 값을 얻는 일반적인 방법


Optional<Object> cc = Optional.ofNullable(null);
// 1. 如果为空的时候获取值就会直接报错
Object o = cc.get();
// 2. 如果对象为空,则获取 or 中的 get 方法的值,否则则获取cc的 get 方法中的值
Object o1 = cc.or(() -> Optional.ofNullable("123")).get();
// 3. 如果对象为空,则直接获取的是 123, orElse()中的参数是非空的。 如果对象不为空则直接获取到对象的值
Object o2 = cc.orElse("123");
// 4. 如果对象为空,则获取 or 中的 get 方法的值,否则则获取cc的 get 方法中的值
Object o3 = cc.orElseGet(() -> Optional.ofNullable("123"));

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

2.1.3 일반적인 판단 방법

Optional<Object> cc = Optional.ofNullable(null);
// 1. 存在则返回true
boolean present = cc.isPresent();
// 2. 为null返回true
boolean empty = cc.isEmpty();
  • 1
  • 2
  • 3
  • 4
  • 5

2.1.4 판정 후의 동작 방법


Optional<Object> cc = Optional.ofNullable(null);
// 1. 如果对象不为空,则执行方法体的内容,否则没有任何操作
cc.ifPresent(item->{
    System.out.println("不为空则执行我"+item);
});

// 2. 如果对象不为空,则执行方法体的内容,否则没有任何操作
cc.ifPresentOrElse(item->{
    System.out.println("不为空则执行我"+item);
},()->{
    System.out.println("为空则执行我");
});

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

2.2 지도 방법 소개

map 方法的使用跟 Stream 中的map方法一样,我的理解这里面的所有的接口方法与 Stream 中重名的用法都是一样的
  • 1

@Data
public static class User{
    private String name;
    private Integer age;
}
@Test
void getMapTest(){

    User user = new User();
    user.setName("123");
    Optional<User> optionalUser = Optional.of(user);
    // 1. 直接获取 user 对象的 name 的值,这里 map 是当用户不为空的时候执行的
    Optional<String> name = optionalUser.map(User::getName);
    System.out.println(name.isEmpty()); // 输出 false

    Optional<User> optionalUser2 = Optional.ofNullable(null);
    // 2. 直接获取 user 对象的 name 的值,这里 map 是当用户不为空的时候执行的
    Optional<String> name2 = optionalUser2.map(User::getName);
    System.out.println(name2.isEmpty()); // 输出 true
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

2.2 기타 방법

다른 방법:

2.2.1 필터 방식

filter : 이 방법은 필터링을 위한 것이며,Optional<Path> p = uris. stream().filter(uri -> !isProcessedYet(uri)).findFirst() .map(Paths::get); 기본적으로 여기서는 사용한 적이 없으며 사용 시나리오가 없는 것 같습니다.

2.2.2 FlatMap 방법

flatMap: 나는 이 방법을 unboxing 변환으로 이해합니다. 예를 들어, Stream<Optional<T>> 로 변환하다Optional<T>

Stream<Optional<T>> os = ....
Stream<T> s = os.flatMap(Optional::stream)
  • 1
  • 2

3. 일반적으로 사용되는 예

TODO 这里后面再不吧,暂时也没有太合适的例子
  • 1

4. 요약

Optional Java 8에 도입된 이 방법은 잠재적인 null 값을 처리하는 보다 우아하고 안전한 방법을 제공합니다.주로 통해or ,orElse , ifPresent 빈 공간을 우아하게 결정하고 비어 있지 않은 후에 작업을 실행하는 기능적 메서드를 기다리는 것은 여러 계층의 작업을 줄일 수 있습니다.if 판단은 코드를 우아하게 만들지 만 단점은 다음과 같습니다.函数式 방법을 사용하면 코드의 가독성이 떨어집니다.그리고 또한 필요Lambda 어느 정도의 이해가 필요합니다.