ホームページ  >  記事  >  Java  >  Java 8 の新しい API -- Optional の使用例

Java 8 の新しい API -- Optional の使用例

零下一度
零下一度オリジナル
2017-05-24 11:40:221954ブラウズ

Java 8 には非常に便利な API がいくつか追加されていることはわかっていますが、そのうちの 1 つはオプションです。少し詳しく調べなければ、NullPointException の問題をエレガントに解決できるだろうと軽く考えて、コードを書き始めます。このように

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

} else {return Collections.emptyList();

}

次に、私たちの考え方は依然として同じであると言わざるを得ませんが、これは本質的には以前に書いたものと同じです

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

} else {return Collections.emptyList();

}

。は、Java 8 の上手な使い方についてお話します。 オプションの正しい姿勢です。

リオオリンピック中、ニュースで五つ星の赤旗に問題があると繰り返し取り上げられていましたが、私にはわかりませんでした。どう見ても問題はありませんでしたが、この小さな星の礼拝の姿勢が間違っていたことが分かりました。つまり、Java 8 の Optional に切り替えると、これまでの null の扱い方を継承できなくなります。 はっきり言って、新しい Java 8 Optional を正しく使用するための正しい姿勢をマスターする必要があります。 、次の方法でまだ Optional を使用しているときは、自分自身のチェックを開始する必要があります

    isPresent() メソッドを呼び出すとき
  1. get() メソッドを呼び出すとき
  2. クラスとしての Optional 型/インスタンス属性
  3. メソッドパラメータとしてのオプションの型
  4. isPresent() は obj != null と違いはありません。Bu Bu Jing Xin では 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.

(最初に isPresent() を使用して値が利用可能かどうかを確認せずに Optional.get() を呼び出すと、IntelliJ IDEA で警告が表示されます。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 のような型をフィールドまたはメソッドのパラメーターとして使用することはお勧めできません)。 これは、値がない場合に戻り値の型を明確に示すことができる

クラス ライブラリ

メソッドとしてのみ設計されています。オプションの型はシリアル化できず、フィールド型として使用すると問題が発生します)
それでは、何ができるのかを説明します。 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

私は、おおよその使用頻度に従って上記のメソッドを分類したことに多少の自信があります

まず。何よりも、3 種類の Optional Construction メソッドについて言及する必要があります: 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() は値がある場合は直接戻り、値がない場合はエラーをスローします

一文の要約: Optional を使用する場合は、Optional.get() メソッドを直接呼び出さないようにしてください。Optional.isPresent() はプライベート メソッドとみなされ、Optional.orElse()、Optional などの他のメソッドに依存する必要があります。 .orElseGet()、Optional.map() などのメソッドです。

最後に、Java 8 Optional を理解する最良の方法は、そのソース コード java.util.Optional を確認することです。 ソースコードを読んで初めて自信を持って説明できます。オプションのメソッドは基本的に内部で isPresent() の判定が行われ、true の場合は値が処理され、false の場合は何も行われません。

1.

Java 8 で新しく導入された Optional クラス インスタンスのコードを共有します

2. Java 8 Optional クラス インスタンスのチュートリアル

以上がJava 8 の新しい API -- Optional の使用例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。