你的错误,关键是在类型的泛型声明F:F extends Function<T, R>。无效的语句是:new Builder<MyInterface>().with(MyInterface::getNumber, 4L);首先,您有一个new Builder<MyInterface>。因此,该类的声明暗含T = MyInterface。按你的声明with,F必须是Function<T, R>,这是Function<MyInterface, R>在这种情况下。因此,该参数getter必须采用a MyInterface作为参数(方法引用MyInterface::getNumber和满足MyInterface::getLong),然后返回R,该参数必须与该函数的第二个参数具有相同的类型with。现在,让我们看看这是否适用于所有情况:
// T = MyInterface, F = Function<MyInterface, Long>, R = Long
new Builder<MyInterface>().with(MyInterface::getLong, 4L);
// T = MyInterface, F = Function<MyInterface, Number>, R = Number
// 4L explicitly widened to Number
new Builder<MyInterface>().with(MyInterface::getNumber, (Number) 4L);
// T = MyInterface, F = Function<MyInterface, Number>, R = Number
// 4L implicitly widened to Number
new Builder<MyInterface>().<Function<MyInterface, Number>, Number>with(MyInterface::getNumber, 4L);
// T = MyInterface, F = Function<MyInterface, Number>, R = Number
// 4L implicitly widened to Number
new Builder<MyInterface>().with((Function<MyInterface, Number>) MyInterface::getNumber, 4L);
// T = MyInterface, F = Function<MyInterface, Number>, R = Long
// F = Function<T, not R> violates definition, therefore compilation error occurs
// Compiler cannot infer type of method reference and 4L at the same time, 
// so it keeps the type of 4L as Long and attempts to infer a match for MyInterface::getNumber,
// only to find that the types don't match up
new Builder<MyInterface>().with(MyInterface::getNumber, 4L);
您可以使用以下选项“解决”此问题:
// stick to Long
new Builder<MyInterface>().with(MyInterface::getLong, 4L);
// stick to Number
new Builder<MyInterface>().with(MyInterface::getNumber, (Number) 4L);
// explicitly convert the result of getNumber:
new Builder<MyInterface>().with(myInstance -> (Long) myInstance.getNumber(), 4L);
// explicitly convert the result of getLong:
new Builder<MyInterface>().with(myInterface -> (Number) myInterface.getLong(), (Number) 4L);
除此之外,这主要是一个设计决定,即哪种选择可以降低特定应用程序的代码复杂度,因此请选择最适合自己的选择。
不进行强制转换就无法执行此操作的原因在于Java语言规范中的以下内容:
  装箱转换将原始类型的表达式视为相应引用类型的表达式。具体来说,以下九种转换称为装箱转换:  
  
  
  - 从布尔类型到布尔类型
- 从字节类型到字节类型
- 从短类型到短类型
- 从char类型到Character类型
- 从int类型到Integer类型
- 从长型到长型
- 从浮点型到浮点型
- 从Double类型到Double类型
- 从空类型到空类型
正如您可以清楚地看到的那样,没有从long到Number的隐式装箱转换,并且只有在编译器确定它需要一个Number而不是Long时,才可能发生从Long到Number的扩展转换。由于需要Number的方法引用与提供Long的4L之间存在冲突,因此编译器(由于某种原因?)无法做出Long is-a Number的逻辑飞跃并推论出Fa Function<MyInterface, Number>。
相反,我设法通过稍微编辑功能签名来解决该问题:
public <R> Builder<T> with(Function<T, ? super R> getter, R returnValue) {
  return null;//TODO
}
进行此更改后,将发生以下情况:
// doesn't work, as it should not work
new Builder<MyInterface>().with(MyInterface::getLong, (Number), 4L);
// works, as it always did
new Builder<MyInterface>().with(MyInterface::getLong, 4L);
// works, as it should work
new Builder<MyInterface>().with(MyInterface::getNumber, (Number)4L);
// works, as you wanted
new Builder<MyInterface>().with(MyInterface::getNumber, 4L);
编辑:
 
花了更多时间后,很难实施基于getter的类型安全。这是一个使用setter方法强制执行构建器的类型安全性的工作示例:
public class Builder<T> {
  static public interface MyInterface {
    //setters
    void number(Number number);
    void Long(Long Long);
    void string(String string);
    //getters
    Number number();
    Long Long();
    String string();
  }
  // whatever object we're building, let's say it's just a MyInterface for now...
  private T buildee = (T) new MyInterface() {
    private String string;
    private Long Long;
    private Number number;
    public void number(Number number)
    {
      this.number = number;
    }
    public void Long(Long Long)
    {
      this.Long = Long;
    }
    public void string(String string)
    {
      this.string = string;
    }
    public Number number()
    {
      return this.number;
    }
    public Long Long()
    {
      return this.Long;
    }
    public String string()
    {
      return this.string;
    }
  };
  public <R> Builder<T> with(BiConsumer<T, R> setter, R val)
  {
    setter.accept(this.buildee, val); // take the buildee, and set the appropriate value
    return this;
  }
  public static void main(String[] args) {
    // works:
    new Builder<MyInterface>().with(MyInterface::Long, 4L);
    // works:
    new Builder<MyInterface>().with(MyInterface::number, (Number) 4L);
    // compile time error, as it shouldn't work
    new Builder<MyInterface>().with(MyInterface::Long, (Number) 4L);
    // works, as it always did
    new Builder<MyInterface>().with(MyInterface::Long, 4L);
    // works, as it should
    new Builder<MyInterface>().with(MyInterface::number, (Number)4L);
    // works, as you wanted
    new Builder<MyInterface>().with(MyInterface::number, 4L);
    // compile time error, as you wanted
    new Builder<MyInterface>().with(MyInterface::number, "blah");
  }
}
提供了构造对象的类型安全功能,希望在将来的某个时候,我们能够从构建器返回一个不可变的数据对象(也许通过向toRecord()接口添加方法,并将构建器指定为Builder<IntermediaryInterfaceType, RecordType>),因此您甚至不必担心结果对象被修改。坦白地说,要获得类型安全的字段灵活的生成器需要大量的精力,这是绝对的耻辱,但是如果没有一些新功能,代码生成或令人讨厌的反射,这可能是不可能的。
               
              
MyInterface吗?