>  기사  >  Java  >  Java 8의 새로운 API - Optional 사용 예

Java 8의 새로운 API - Optional 사용 예

零下一度
零下一度원래의
2017-05-24 11:40:222003검색

우리는 Java 8에 몇 가지 매우 유용한 API가 추가되었다는 것을 알고 있으며 그 중 하나는 Optional입니다. 조금만 살펴보지 않으면 이것이 NullPointException 문제를 우아하게 해결할 수 있다고 가볍게 생각하므로 코드는 다음과 같이 시작됩니다. 이렇게 작성하세요

Optional4c8e0c17c3bd7e0081bb17cc795e1984 user = ......if (user.isPresent()) {return user.getOrders();

} else {return Collections.emptyList();

}

그렇다면 우리의 생각은 여전히 ​​같은 곳에 있지만 본능적으로는 User 인스턴스에 대한 래퍼일 뿐이라고 생각해야 합니다. 이는 본질적으로 우리가 작성한 것과 동일합니다.

User user = .....if (user != null) {return user.getOrders();

} else {return Collections.emptyList();

}

입니다. 이것이 바로 우리가 이야기할 Java 8 Optional 타입을 사용하는 올바른 자세입니다.

리우 올림픽 기간 동안 뉴스에서는 이런 일이 반복적으로 언급되었습니다. 별 다섯개짜리 깃발이 문제인데 아무리 봐도 문제가 보이지 않았다. 나중에 문제는 작은 별이 중심을 숭배하는 자세가 옳지 않다는 것이다. 우리는 당연한 것에 익숙해져 있어서 전혀 잘못된 점을 느끼지 못할 것입니다. 즉, Java 8의 Optional로 전환하면 속성을 상속받을 수 없습니다. 과거에 null에 대해 생각하는 대신 새롭고 올바른 것을 마스터해야 합니다. Java 8 Optional 사용 자세.

직설적으로 말하면, 여전히 다음과 같은 Optional을 사용하고 있을 때, 스스로 점검을 시작해야 합니다

  1. isPresent() 메소드

  2. get() 메소드를 호출할 때

  3. Optional 타입을 클래스/인스턴스 속성으로 사용할 때

  4. Optional 타입을 메소드 인자로 사용한 경우

isPresent() with obj != null 별차이가 없어 우리 삶은 여전히 ​​충격적인 발걸음 그리고 isPresent()가 없는 get() 호출은 IntelliJ IDEA에서

Reports calls to java.util.Optional.get() without first checking with a isPresent() call if a value is available. If the Optional does not contain a value, get() will throw an exception.

경고를 받게 됩니다(이전에 Optional.get()을 호출할 필요가 없습니다. isPresent()를 사용하여 값을 사용할 수 있는지 미리 확인하세요. ). Optional에 값이 없으면 get() 예외가 발생합니다)

IntelliJ IDEA에서는 Optional 유형을 속성이나 메소드 매개변수로 사용하는 것을 강력히 권장하지 않습니다

Reports any uses of java.util.Optional<T>, java.util.OptionalDouble, java.util.OptionalInt, java.util.OptionalLong or com.google.common.base.Optional as the type 
for
 a field or a parameter. Optional was designed to provide a limited mechanism for library method
 return types where there needed to be a 
clear
 way to represent "no result". Using a field with type java.util.Optional is also problematic if the 
class
 needs to be Serializable, which java.util.Optional is not.

(Optional과 같은 유형을 사용하는 것은 권장되지 않습니다) 필드 또는 메소드 매개변수로. 클래스 라이브러리 메소드로만 설계되어 값이 없을 수 있는 경우 반환 유형을 명확하게 나타낼 수 있으며, 선택적 유형은 직렬화할 수 없으며 필드 유형으로 사용할 경우 문제가 발생합니다.)

그래서 Optional에서 우리가 실제로 의지할 수 있는 것은 isPresent() 및 get() 이외의 다른 메소드여야 합니다.

public<U> Optional<U> map(Function<? super T, ? extends U> mapper)
public T orElse(T other)
public T orElseGet(Supplier<? extends T> other)
public void ifPresent(Consumer<? super T> consumer)
public Optional<T> filter(Predicate<? super T> predicate)
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X

저는 위 메소드의 순위를 다음과 같이 매겼다고 어느 정도 확신합니다. 대략적인 사용 빈도부터 시작하겠습니다.

먼저 Optional의 세 가지 구성 방법인 Optional.of(obj), Optional.ofNullable(obj) 및 명시적 Optional.empty()

    Optional.of(obj) : 它要求传入的 obj 不能是 null 值的, 否则还没开始进入角色就倒在了 NullPointerException 异常上了.Optional.ofNullable(obj) : 它以一种智能的, 宽容的方式来构造一个 Optional 实例. 来者不拒, 传 null 进到就得到 Optional.empty() , 非 null 就调Optional.of(obj) .

那是不是我们只要用 Optional.ofNullable(obj) 一劳永逸, 以不变应二变的方式来构造 Optional 实例就行了呢? 那也未必, 否则 Optional.of(obj) 何必如此暴露呢, 私有则可?

我本人的观点是:  1. 当我们非常非常的明确将要传给 Optional.of(obj) 的 obj 参数不可能为 null 时, 比如它是一个刚 new 出来的对象( Optional.of(new User(...)) ), 或者是一个非 null 常量时;  2. 当想为 obj 断言不为 null 时, 即我们想在万一 obj 为 null 立即报告 NullPointException 异常, 立即修改, 而不是隐藏空指针异常时, 我们就应该果断的用 Optional.of(obj) 来构造 Optional 实例, 而不让任何不可预计的 null 值有可乘之机隐身于 Optional 中.

现在才开始怎么去使用一个已有的 Optional 实例, 假定我们有一个实例 Optional4c8e0c17c3bd7e0081bb17cc795e1984 user , 下面是几个普遍的, 应避免 if(user.isPresent()) { ... } else { ... } 几中应用方式.

存在即返回, 无则提供默认值

return user.orElse(null);  //而不是 return user.isPresent() ? user.get() : null;return user.orElse(UNKNOWN_USER);

存在即返回, 无则由函数来产生

return user.orElseGet(() -> fetchAUserFromDatabase()); //而不要 return user.isPresent() ? user: fetchAUserFromDatabase();

存在才对它做点什么

user.ifPresent(System.out::println);//而不要下边那样if (user.isPresent()) {
  System.out.println(user.get());
}

map 函数隆重登场

当 user.isPresent() 为真, 获得它关联的 orders , 为假则返回一个空集合时, 我们用上面的 orElse , orElseGet 方法都乏力时, 那原本就是 map 函数的责任, 我们可以这样一行

return user.map(u -> u.getOrders()).orElse(Collections.emptyList())//上面避免了我们类似 Java 8 之前的做法if(user.isPresent()) {  return user.get().getOrders();
} else {  return Collections.emptyList();
}

map 是可能无限级联的, 比如再深一层, 获得用户名的大写形式

return user.map(u -> u.getUsername())
           .map(name -> name.toUpperCase())
           .orElse(null);

这要搁在以前, 每一级调用的展开都需要放一个 null 值的判断

User user = .....if(user != null) {
  String name = user.getUsername();  if(name != null) {    return name.toUpperCase();
  } else {    return null;
  }
} else {  return null;
}

针对这方面 Groovy 提供了一种安全的属性/方法访问操作符 ?.

user?.getUsername()?.toUpperCase();

Swift 也有类似的语法, 只作用在  Optional 的类型上.

用了 isPresent() 处理 NullPointerException 不叫优雅, 有了  orElse, orElseGet 等, 特别是 map 方法才叫优雅.

그 외 몇 가지, filter()는 정규화되지 않은 값을 empty()로 바꾸고, flatMap()은 항상 map() 메서드와 쌍을 이루며, orElseThrow()는 값이 있을 때 직접 반환하고, 값이 없을 때 던집니다. value 원하는 예외가 발생합니다.

한 문장 요약: Optional을 사용할 때 Optional.isPresent() 메서드를 직접 호출하지 마십시오. Optional..orElse() , Optional.orElseGet() , Optional.map() 및 기타 메소드.

마지막으로 Java 8 Optional을 이해하는 가장 좋은 방법은 소스 코드 java를 살펴보는 것입니다. .util.선택 사항, 소스 코드를 읽어야만 설명에 자신감을 가질 수 있습니다. 선택적 메소드는 기본적으로 판단을 위해 isPresent()를 호출합니다. true이면 값이 처리되고, false이면 아무것도 수행되지 않습니다. 관련 추천사항】


1.

Java 8에서 새로 도입된 Optional 인스턴스 코드 공유

2. Java 8 Optional 클래스 분석 인스턴스 튜토리얼

위 내용은 Java 8의 새로운 API - Optional 사용 예의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.