作为一个更具描述性的界面,我想创建以下内容:@FunctionalInterfacepublic interface Dial extends Function<Double,Double> {}但是,当我尝试像这样组成Dial实例时:public class DialExample { public Dial dialMult (double mult) { return (i -> i * mult); } public void myTest () { // Yes Function<Double,Double> f1 = dialMult(3.0).andThen(dialMult(4.0)); // No Dial d1 = dialMult(3.0).andThen(dialMult(4.0)); }}// No注释下的代码给我以下编译错误: 错误:(22、40)Java:不兼容的类型:没有任何类型的实例 存在变量V java.util.function.Function符合 Lambdas.Dial当然,在// Yes注释下的代码可以正常工作,但它首先达到了具有描述性的Dial接口的目的。我有几个问题:Java泛型和lambda的设计/实现是什么导致的这个问题?有解决方法吗?它甚至是一个好习惯子类Function<Double,Double>作为我的描述性接口还是我应该首先避免这种情况? 最佳答案 从default继承的Function方法声明为返回Function,并且通过子default调用interface方法时,该方法不变。请注意,Function.andThen允许将您的Dial实例与任意Function组合,并返回不同的类型,从而创建与Function的功能签名不兼容的Dial:Function<Double,String> f=dialMult(3.0).andThen(Object::toString);但是,如果类型匹配,则可以即时转换Function:Dial d1 = dialMult(3.0).andThen(dialMult(4.0))::apply;另外,您可以创建自己的andThen方法。请注意,此方法不会覆盖Function.andThen(Function)方法,因为这将需要限制第二个函数的允许类型参数,这将是无效的参数变窄。但是,对于组合两个Dial实例(或Dial实例与UnaryOperator<Double>),它可以工作。@FunctionalInterfacepublic interface Dial extends UnaryOperator<Double> { public default Dial andThen(UnaryOperator<Double> after) { return d->after.apply(apply(d)); }}既然上面的方法为什么不覆盖Function.andThen(Function)的解释似乎太简短了,所以让我详细介绍一下:如开头所述,从andThen继承的Function方法允许参数函数具有任意返回类型,在示例中使用返回String而不是Double的函数对此进行了说明。应用Dial为其超级类型指定类型参数时,有效签名变为:public interface Dial extends UnaryOperator<Double> { @Override public default <R> Function<Double, R> andThen(Function<? super Double, ? extends R> after) { return UnaryOperator.super.andThen(after); }}重写此方法时,可以声明更特定的返回类型,即Function的子接口,但是,它必须与Function<Double, R>类型兼容,而Dial则不是这样,因为Dial扩展。这将需要限制参数,以仅允许对Function<Double,Double>使用Double,这是不允许的。为了有效地替代R,子接口本身必须是通用的,才能使用Function<Double, R>进行参数设置。
09-25 21:23