【问题标题】:Optional.orElse does not compile with anonymous typesOptional.orElse 不使用匿名类型编译
【发布时间】:2019-12-03 13:53:34
【问题描述】:

我在使用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() {
        });
    }
}

前两种方法无法编译并报错

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

我预料到了,因为两者都实现了接口Bar,所有三种方法都可以工作。我也无法弄清楚为什么第三个选项可以解决问题。谁能解释一下?

【问题讨论】:

  • 第三个解决了这个问题,因为Optional.of 的类型固定为Optional&lt;Bar&gt;。在所有其他情况下,它是Optional&lt;SubAnonymousSubclassOfBar&gt;。不过,我本来希望其他两个也能对Bar 的适当公共上限进行类型推断。但显然Optional&lt;SomeSubclassOfBar&gt;(bar).orElse(someOtherSubclassOfBar) 需要一些帮助。

标签: java optional anonymous-class


【解决方案1】:

您可以使用类型见证来补充前两个的类型:

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

这使编译器可以看到您期望返回Optional&lt;Bar&gt;,然后#orElse 可以推断出接受任何Bar

【讨论】:

    【解决方案2】:

    您需要告诉 Optional 您想要该界面的 Bar。

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

    【讨论】:

    • 我知道泛型是干什么用的。我只是认为 javac 会像@Thilo 所说的那样推断类型。
    • 是的,来自 Scala,不得不把这个拼出来有点蹩脚。另一方面,javac 的编译速度要快得多,所以 ...
    • @Mirco 它推断'匿名类型扩展 Bar'。如果那不是你想要的,你必须说明你的意图。
    【解决方案3】:

    案例compiles1

    您的Optional 具有泛型类型Bar,因为变量bar 具有类型Bar

    您创建的Foo$1 类型的匿名类具有Bar 作为超类型,因此该方法可以编译。

    案例doesNotCompile

    这里,Optional 具有泛型类型Foo$1,而您正试图将Foo$2 类型的对象传递给orElse,它没有Foo$1 作为超类型。因此编译错误。

    案例doesNotCompile2

    类似于doesNotCompileOptional 具有泛型类型Foo$1,而您正试图将barBar 类型的变量)传递给orElse,而orElse 又没有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() {
            });
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-09
      相关资源
      最近更新 更多