Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java8/Lambdas/Streams:子类化函数<;T、 R>;导致Andhen()方法出现问题_Java_Java 8_Java Stream - Fatal编程技术网

Java8/Lambdas/Streams:子类化函数<;T、 R>;导致Andhen()方法出现问题

Java8/Lambdas/Streams:子类化函数<;T、 R>;导致Andhen()方法出现问题,java,java-8,java-stream,Java,Java 8,Java Stream,作为更具描述性的界面,我想创建以下内容: @FunctionalInterface public interface Dial extends Function<Double,Double> {} //No注释下的代码给出了以下编译错误: 错误:(22,40)java:不兼容的类型:没有类型为的实例 变量V的存在使得 java.util.function.function符合 兰博达斯。表盘 当然//Yes注释下的代码是有效的,但它首先破坏了使用描述性拨号接口的目的 我有几个问题:

作为更具描述性的界面,我想创建以下内容:

@FunctionalInterface
public interface Dial extends Function<Double,Double> {}
//No
注释下的代码给出了以下编译错误:

错误:(22,40)java:不兼容的类型:没有类型为的实例 变量V的存在使得 java.util.function.function符合 兰博达斯。表盘

当然
//Yes
注释下的代码是有效的,但它首先破坏了使用描述性
拨号接口的目的

我有几个问题:

  • Java泛型和lambda的设计/实现带来了什么 这个问题怎么办
  • 有解决办法吗
  • 这是一个很好的实践吗 子类
    函数
    作为像我这样的描述性接口 或者我应该首先避免这样做

    • 的定义是

      default <V> Function<T,V> andThen(Function<? super R,? extends V> after)
      

      默认函数,然后(函数可以找到
      的签名。它清楚地表明
      返回
      函数,而不是
      拨号


      Java没有很好的方法为类型创建类型安全别名。

      函数
      继承的
      默认
      方法被声明为返回
      函数
      ,当通过子
      接口
      调用
      默认
      方法时,这一点不会改变。请注意,
      函数。然后,
      允许将<代码>拨号
      实例,具有任意的
      函数
      返回不同类型,创建的
      函数
      与您的
      拨号
      的功能签名不兼容:

      Function<Double,String> f=dialMult(3.0).andThen(Object::toString);
      

      或者,您可以创建自己的
      和第二个
      方法。请注意,此方法不会覆盖
      函数。第二个(函数)
      方法需要限制第二个函数允许的类型参数,这将是一个无效的参数收缩。但用于组合两个
      拨号
      实例(或使用
      unarycoperator
      拨号
      实例)它可以工作

      @FunctionalInterface
      public interface Dial extends UnaryOperator<Double> {
          public default Dial andThen(UnaryOperator<Double> after) {
              return d->after.apply(apply(d));
          }
      }
      

      重写此方法时,可以声明更具体的返回类型,即
      函数
      的子接口,但是,它必须与
      函数
      的类型兼容,这与
      拨号
      不同,因为
      拨号
      扩展了
      函数
      。这需要将参数限制为仅允许
      Double
      用于
      R
      ,这是不允许的。要有效替代
      功能
      ,子接口本身必须是通用的,才能使用

      参数化
      拨号
      功能
      ,但
      功能
      不一定是
      拨号
      。最好使用
      双功能YoOperator
      ,或者至少是
      UniaryOperator
      ,而不是
      函数
      。您的
      拨号
      界面基本上是
      DoubleUniaryOperator
      界面的克隆,但没有原语。答案的后半部分(“或者…”)工作非常完美,这正是我想要的。请注意,您还可以对
      进行简单的协变重写,然后
      只优化返回类型并保持参数常量。然后这确实是一个重写,只需使用协变返回类型即可(此功能是在Java5中添加的,同样适用于默认方法。)@Brian Goetz:正如我在回答中所解释的,这正是你不能做的。
      然后
      接受一个具有任意返回类型的任意函数,并且必须返回一个返回类型与第二个函数兼容的
      函数
      。因此,你不能覆盖它来返回一个总是EXT的
      拨号
      实例nds
      函数
      。这需要将
      函数
      的参数限制为
      函数
      ,这是不可能的。我对我的答案添加了更详细的解释…如何。如果不修改函数接口,我看不到通过添加一个表示实际派生接口的通用参数来实现这一点的方法。它看起来很难看
      Function<Double,String> f=dialMult(3.0).andThen(Object::toString);
      
      Dial d1 = dialMult(3.0).andThen(dialMult(4.0))::apply;
      
      @FunctionalInterface
      public interface Dial extends UnaryOperator<Double> {
          public default Dial andThen(UnaryOperator<Double> after) {
              return d->after.apply(apply(d));
          }
      }
      
      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);
          }
      }