Java 8 Optional不能应用于接口

时间:2019-01-17 14:52:57

标签: java generics lambda java-8 optional

使用Optional,我想根据映射结果返回接口的某个实现(FirstSecond)。这是First和{ {1}}实现:

Second

以下public interface MyInterface { Number number(); } 用法是错误的:

Optional
  不能将

orElse final String string = ... // might be null final Number number = Optional.ofNullable(string) .map(string -> new First()) .orElse(new Second()) // erroneous line .number(); 应用于(com.mycompany.First)

为什么由于类(com.mycompany.Second)First都实现了接口Second而方法MyInterface返回MyInterface::number,所以行是错误的?如何正确实现呢?

5 个答案:

答案 0 :(得分:5)

我发现方法Optional::map返回U,这不允许将返回的First应用到另一种类型的Second。显式转换为其接口或在map方法中要求它是一种方法:

final Number number = Optional.ofNullable("")
        .<MyInterface>map(string -> new First())
        .orElse(new Second())
        .number(); 

__

编辑:发布问题后,我发现了这一点。但是,由于我在其他任何地方都找不到类似的解决方案,因此我将两者都保留。

答案 1 :(得分:5)

问题在于Java 推断映射类型为First,而Second不是First的实例。您需要明确地向Java轻推一下才能知道正确的类型:

private static void main(String... args)
{
    final String string = "";
    final Number number = Optional.ofNullable(string)
        .<MyInterface>map(str -> new First())  // Explicit type specified 
        .orElse(new Second())
        .number();
}

这是沿方法链进行类型推断的一般限制。不限于Optional

有人建议在方法链中进行类型推断。看到以下问题:Generic type inference not working with method chaining?

也许在Java的未来版本中,编译器将足够聪明以解决此问题。谁知道。

答案 2 :(得分:2)

我会这样写,而无需显式强制转换:

Optional.ofNullable(string)
        .map(s -> {
             MyInterface m = new First();
             return m;  
        })
        .orElse(new Second())
        .number();

答案 3 :(得分:1)

您也可以写:

Optional.ofNullable(string)
    .map(s -> new First())
    .filter(MyInterface.class::isInstance)
    .map(MyInterface.class::map)
    .orElse(new Second())
    .number()

或者,将实用程序功能添加到您的代码库中:

// the Class Object is unused and only present so the Compiler knows which Type you actually want
public static <T, R> Function<? super T, R> mapAs(Function<? super T, ? extends R> mappingFunction, Class<R> clazz) {
    return mappingFunction::apply;
}
Optional.ofNullable(string)
    .map(mapAs(s -> new First(), MyInterface.class))
    .orElse(new Second())
    .number()

答案 4 :(得分:0)

在其他答案中,解释也是如此,其类型是在使用map时会误认为正在使用的orElse的类型,因此,代表建议解决方案的更简洁的方法是:

Optional.ofNullable(string)
        .map(s -> (MyInterface) new First()) // casting rather than binding here
        .orElse(new Second())
        .number();