web-dev-qa-db-ja.com

Optional.orElseが匿名型でコンパイルされない

Optionalsと匿名クラスを使用して奇妙な問題が発生しました:

public class Foo {
    interface Bar {
    }

    void doesNotCompile() {
        Optional.of(new Bar() {
        }).orElse(new Bar() {
        });
    }

    void doesNotCompile2() {
        final Bar bar = new Bar() {
        };
        Optional.of(new Bar() {
        }).orElse(bar);
    }

    void compiles1() {
        final Bar bar = new Bar() {
        };
        Optional.of(bar).orElse(new Bar() {
        });
    }
}

最初の2つのメソッドはエラーでコンパイルされません

Java: incompatible types: <anonymous test.Foo.Bar> cannot be converted to <anonymous test.Foo.Bar>

どちらもBarインターフェースを実装しているので、3つのアプローチすべてが機能することを期待していました。 3番目のオプションで問題が解決される理由もわかりません。誰かがこれを説明できますか?

8
Mirco

タイプウィットネスを使用して、最初の2つのタイプを補足できます。

Optional.<Bar>of(new Bar(){}).orElse(new Bar(){});

これにより、コンパイラーはOptional<Bar>の戻りを期待していることを確認できます。#orElseは、Barの受け入れを推測できます。

7
Rogue

あなたは、そのインターフェースにバーが必要であることをオプションに伝える必要があります。

Bar bar = new Bar();
Optional<Bar> o = Optional.of(new Bar() {}).orElse(bar);
5
Nicktar

ケース_compiles1_

変数Optionalの型がBarであるため、barのジェネリック型はBarです。

作成する_Foo$1_型の匿名クラスは、スーパータイプとしてBarを持っているため、メソッドはコンパイルされます。

ケースdoesNotCompile

ここでは、Optionalのジェネリック型は_Foo$1_であり、_Foo$2_をスーパータイプとして持たないorElseに_Foo$1_型のオブジェクトを渡そうとしています。したがって、コンパイルエラーです。

ケース_doesNotCompile2_

doesNotCompileと同様に、Optionalのジェネリック型は_Foo$1_であり、barの型の変数であるBarorElseに渡そうとしていますが、_Foo$1_がスーパー型として再びありません。


これらのエラーを回避する

_Optional::of_の呼び出しにタイプウィットネスを追加します。これにより、Optionalにジェネリック型Barが付与されます。

_public class Foo {

    interface Bar {
    }

    void doesNotCompile() {
        Optional.<Bar>of(new Bar() {
        }).orElse(new Bar() {
        });
    }

    void doesNotCompile2() {
        final Bar bar = new Bar() {
        };
        Optional.<Bar>of(new Bar() {
        }).orElse(bar);
    }

    void compiles1() {
        final Bar bar = new Bar() {
        };
        Optional.of(bar).orElse(new Bar() {
        });
    }
}
_
5
Marv