为什么编译时不检查 lambda 返回类型?

使用的方法引用具有返回类型Integer。String但在下面的示例中,不兼容是允许的。


如何修复方法with声明以获得方法引用类型安全而无需手动转换?


import java.util.function.Function;


public class MinimalExample {

  static public class Builder<T> {

    final Class<T> clazz;


    Builder(Class<T> clazz) {

      this.clazz = clazz;

    }


    static <T> Builder<T> of(Class<T> clazz) {

      return new Builder<T>(clazz);

    }


    <R> Builder<T> with(Function<T, R> getter, R returnValue) {

      return null; //TODO

    }


  }


  static public interface MyInterface {

    Integer getLength();

  }


  public static void main(String[] args) {

// missing compiletimecheck is inaceptable:

    Builder.of(MyInterface.class).with(MyInterface::getLength, "I am NOT an Integer");


// compile time error OK: 

    Builder.of(MyInterface.class).with((Function<MyInterface, Integer> )MyInterface::getLength, "I am NOT an Integer");

// The method with(Function<MinimalExample.MyInterface,R>, R) in the type MinimalExample.Builder<MinimalExample.MyInterface> is not applicable for the arguments (Function<MinimalExample.MyInterface,Integer>, String)

  }


}


扬帆大鱼
浏览 120回答 4
4回答

子衿沉夜

在第一个示例中,和MyInterface::getLength分别帮助"I am NOT an Integer"解析通用参数T和。RMyInterfaceSerializable & Comparable<? extends Serializable & Comparable<?>>// it compiles since String is a SerializableFunction<MyInterface, Serializable> function = MyInterface::getLength;Builder.of(MyInterface.class).with(function, "I am NOT an Integer");MyInterface::getLength并不总是 a ,Function<MyInterface, Integer>除非您明确这么说,这会导致编译时错误,如第二个示例所示。// it doesn't compile since String isn't an IntegerFunction<MyInterface, Integer> function = MyInterface::getLength;Builder.of(MyInterface.class).with(function, "I am NOT an Integer");

翻过高山走不出你

类型推断在这里发挥了作用。R考虑方法签名中的泛型:<R>&nbsp;Builder<T>&nbsp;with(Function<T,&nbsp;R>&nbsp;getter,&nbsp;R&nbsp;returnValue)在所列情况中:Builder.of(MyInterface.class).with(MyInterface::getLength,&nbsp;"I&nbsp;am&nbsp;NOT&nbsp;an&nbsp;Integer");的类型R被成功推断为Serializable,&nbsp;Comparable<?&nbsp;extends&nbsp;Serializable&nbsp;&&nbsp;Comparable<?>>并且 aString确实通过这种类型暗示,因此编译成功。要显式指定 的类型R并找出不兼容性,只需将代码行更改为:Builder.of(MyInterface.class).<Integer>with(MyInterface::getLength,&nbsp;"not&nbsp;valid");

紫衣仙女

这是因为你的泛型类型参数R可以被推断为 Object,即以下编译:Builder.of(MyInterface.class).with((Function<MyInterface,&nbsp;Object>)&nbsp;MyInterface::getLength,&nbsp;"I&nbsp;am&nbsp;NOT&nbsp;an&nbsp;Integer");

梦里花落0921

这个答案基于其他答案,这些答案解释了为什么它不能按预期工作。解决方案下面的代码通过将双函数“with”拆分为两个连贯函数“with”和“returning”来解决该问题:class Builder<T> {...class BuilderMethod<R> {&nbsp; final Function<T, R> getter;&nbsp; BuilderMethod(Function<T, R> getter) {&nbsp; &nbsp; this.getter = getter;&nbsp; }&nbsp; Builder<T> returning(R returnValue) {&nbsp; &nbsp; return Builder.this.with(getter, returnValue);&nbsp; }}<R> BuilderMethod<R> with(Function<T, R> getter) {&nbsp; return new BuilderMethod<>(getter);}...}MyInterface z = Builder.of(MyInterface.class).with(MyInterface::getLength).returning(1L).with(MyInterface::getNullLength).returning(null).build();System.out.println("length:" + z.getLength());// YIPPIE COMPILATION ERRROR:// The method returning(Long) in the type BuilderExample.Builder<BuilderExample.MyInterface>.BuilderMethod<Long> is not applicable for the arguments (String)MyInterface zz = Builder.of(MyInterface.class).with(MyInterface::getLength).returning("NOT A NUMBER").build();System.out.println("length:" + zz.getLength());(有点陌生)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java