Optional.orElse wird nicht mit anonymen Typen kompiliert

8

Bei der Verwendung von Optionals und anonymen Klassen ist ein seltsames Problem aufgetreten :

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() {
        });
    }
}

Die ersten beiden Methoden werden nicht mit dem Fehler kompiliert

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

Ich hatte das erwartet, da beide die Schnittstelle implementieren Bar alle drei Ansätze funktionieren . Ich kann auch nicht herausfinden, warum die dritte Option das Problem behebt. Kann mir das bitte jemand erklären?

Mirco
quelle
2
Der dritte behebt das Problem, da dort der Typ von Optional.ofbehoben ist Optional<Bar>. In allen anderen Fällen ist es Optional<SubAnonymousSubclassOfBar>. Ich hätte erwartet, dass die anderen beiden auch die entsprechende gemeinsame Obergrenze von ableiten würden Bar. Benötigt aber anscheinend Optional<SomeSubclassOfBar>(bar).orElse(someOtherSubclassOfBar)etwas Händchenhalten.
Thilo

Antworten:

7

Sie können den Typ der ersten beiden mit einem Typzeugen ergänzen:

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

Auf diese Weise kann der Compiler sehen, dass Sie eine Rückgabe von erwarten Optional<Bar>, die #orElse dann ableiten kann, um eine zu akzeptierenBar

Schurke
quelle
5

Sie müssen dem Optional mitteilen, dass Sie eine Leiste für diese Schnittstelle wünschen.

Bar bar = new Bar();
Optional<Bar> o = Optional.of(new Bar() {}).orElse(bar);
Nicktar
quelle
1
Ich weiß, wofür Generika sind. Ich dachte nur, dass Javac die Typen ableiten wird, wie @Thilo sagte.
Mirco
3
Ja, von Scala kommend, das buchstabieren zu müssen, ist irgendwie lahm. Auf der anderen Seite javackompiliert so viel schneller, so ...
Thilo
@Mirco schließt es an 'anon Typ verlängernde Stange'. Wenn Sie das nicht wollen, müssen Sie Ihre Absicht angeben.
Nicktar
5

Fall compiles1

Ihr Optionalhat den generischen Typ Bar, weil die Variable barden Typ hat Bar.

Die von Foo$1Ihnen erstellte anonyme Typklasse hatBar einen Supertyp, daher wird die Methode kompiliert.

Fall doesNotCompile

Hier Optionalhat der generische Typ Foo$1und Sie versuchen ein Objekt vom Typ Foo$2zu übergeben, orElsedas nicht hatFoo$1 als Supertyp hat. Daher der Kompilierungsfehler.

Fall doesNotCompile2

Ähnlich doesNotCompile, Optionalhat die allgemeine Art Foo$1und Sie versuchen , passieren bar, eine Variable vom Typ Barin orElsedem wiederum hat nicht Foo$1als Supertyp.


Vermeiden Sie diese Fehler

Fügen Sie Ihrem Anruf von einen Typzeugen hinzu Optional::of. Dies gibt Ihnen Optionalden generischen Typ 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() {
        });
    }
}
Marv
quelle