Optional<ArrayList<String>> option = Optional.of(new ArrayList<>());
Optional<ArrayList<?>> doesntWork = option;
Optional<ArrayList<?>> works = option.map(list -> list);
最初に試行された割り当てはコンパイルされませんが、map
を使用した2番目の割り当てはコンパイルされます。 map
は実際には何も実行すべきではないようですが、何らかの理由でOptional<ArrayList<String>>
をOptional<ArrayList<?>>
に変換します。進行中のある種の暗黙のキャストはありますか?
map
のコードを調べて、すべてのメソッド呼び出しをたどると、option.map(list -> list)
がnew Optional<>(option.get())
を返すことになります。したがって、最後の割り当てを次のように置き換えることができます。
_Optional<ArrayList<?>> works = new Optional<>(option.get());
_
これにより、新しい_Optional<ArrayList<?>>
_が作成され、value
インスタンス変数(タイプは_ArrayList<?>
_)がmap.get()
から返される_ArrayList<String>
_で初期化されます。これは有効な割り当てです。
進行中のある種の暗黙のキャストはありますか?
いいえ、map
は新しいOptional
インスタンスを返します。呼び出された元のインスタンスはキャストされません。
次に、一連のメソッド呼び出しを示します。
_option.map(list -> list)
_
戻り値(option
は空ではないため)
_Optional.ofNullable(mapper.apply(value))
_
これはあなたの場合と同じです
_Optional.ofNullable(value)
_
戻り値(値がnullではないため):
_Optional.of(value)
_
戻る
_new Optional<>(value)
_
ジェネリックは不変なので、最初の方法は機能しません。ジェネリックスを共変にする唯一の方法は、たとえば次のように有界型を追加することです。
Optional<? extends ArrayList<String>> doesntWork = option;
コンパイルされます。
そして、あなたがmap
ステップが何も成し遂げるべきではないと言うとき、それは正しくありません。 Optional::map
の定義を見てください。
public <U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent()) {
return empty();
} else {
return Optional.ofNullable(mapper.apply(value));
}
}
大まかに言えばdoesOptional<T>
からOptional<U>
...に変換.
後者の場合、Optional.map
メソッドの戻り値の型は、works
変数の型によって暗黙的に決定されます。それが違いがある理由です。
君の option.map
には署名があります
<ArrayList<?>> Optional<ArrayList<?>> Java.util.Optional.map(Function<? super ArrayList<String>, ? extends ArrayList<?>> mapper)
したがって、この
Optional<? extends ArrayList<?>> doesntWork = option;
コンパイルしません。