java - 从 Java 8 中的 Function 继承的命名具体接口(interface)

标签 java inheritance types java-8 alias

我有很多地方有 Function<Foo,Foo> .我基本上想将其别名为 FooTransformer .我的第一次尝试是。

interface FooTransformer extends Function<Foo,Foo>{}

当我尝试编写 FooTransformer 时,这以类型系统的投诉告终。

class Foo {}

interface FooTransformer extends Function<Foo,Foo> {}


public void TestFoo(){
    //two differently named identity transforms
    FooTransformer t1 = foo -> foo;
    FooTransformer t2 = foo -> foo;

    FooTransformer t3 = t1.andThen(t2);
}

这失败了

Error:(93, 39) java: incompatible types: no instance(s) of type variable(s) V exist so that java.util.function.Function conforms to org.broadinstitute.hellbender.tools.walkers.bqsr.ReadTransformerTest.FooTransformer

通过修改FooTransformer重载andThen我的代码编译并运行。

interface FooTransformer extends Function<Foo,Foo> {
    default FooTransformer andThen(FooTransformer after){
        return Function.super.andThen(after)::apply;
    }
}

我现在收到这个警告(使用带有 --Xlint:all 的 javac 1.8.0_25)

warning: [overloads] andThen(FooTransformer) in FooTransformer is potentially ambiguous with andThen(Function) in Function default FooTransformer andThen(FooTransformer after){ ^ where V,R,T are type-variables: V extends Object declared in method andThen(Functionextends V>) R extends Object declared in interface Function T extends Object declared in interface Function

我真正想要的是 Function<Foo,Foo> 的类型别名这是我能得到的最接近的。有没有更好的方法可以在没有警告的情况下完成此操作?

最佳答案

我不知道你使用的是哪个编译器,因此我无法测试我提出的解决方案是否会解决你的警告。您收到警告的原因是因为您的 andThen方法与继承方法非常相似 Function.andThen但不会覆盖它。一种可能的解决方案是显式覆盖方法 Function.andThen还有:

interface FooTransformer extends Function<Foo,Foo> {

    @Override
    public default <V> Function<Foo, V> andThen(Function<? super Foo, ? extends V> after) {
        return Function.super.andThen(after);
    }
    default FooTransformer andThen(FooTransformer after){
        Objects.requireNonNull(after);
        return foo -> after.apply(apply(foo));
    }
}

那么应该清楚您知道您的 andThen不会像另一个那样覆盖该方法。但是,如前所述,我无法测试这是否会让警告消失。

此警告可能试图解决另一个方面。如果您使用 interface 重载了方法参数类型,如果有人试图用实现 both 的具体类型调用任一方法,它会产生潜在的歧义 interface秒。这在这里不适用,因为一个参数类型是另一个参数类型的子类型,所以它永远不会模棱两可,但似乎 javac不够聪明,无法识别这一点。因此,您可以与 javac 进行讨论开发人员对此表示希望 future 的版本不会发出警告,但是会添加 @SuppressWarnings("overloads")该方法是更简单的解决方案……


请注意,我将实现更改为不包装 Function.super.andThen 的结果进入FooTransformer .虽然方法引用是将任意接口(interface)实例转换为另一个接口(interface)的好方法,但我认为当实际实现已知并且像本例一样简单时,应该避免将函数包装到另一个函数的开销。


请注意,您可以考虑让您的 FooTransformer扩展 UnaryOperator<Foo> , 这是 Function<Foo,Foo> 的子接口(interface).所以一切都像以前一样工作,但您可以选择使用 FooTransformer 的实例与 List.replaceAll Stream.iterate AtomicReference.updateAndGet ……

关于java - 从 Java 8 中的 Function 继承的命名具体接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28612977/

相关文章:

java - java中的静态 block 和对象 block 访问

Java:查找父级和子级......Tree,Loop,ArrayList,List,HashMap,......做什么?

java - 我无法从扩展 List 接口(interface)的类中调用方法

java - 如果在 linux 上的 jboss 4 中的 JAVA_OPTS 中多次声明变量怎么办

java - 不让我初始化一个最终常量 int 吗?

java - 有关混合重写声明变量和实例变量的问题?

c++ - 使用继承时类的大小是多少?

c - 从 Int 类型分配给类型 'struct PartyInfo' 时不兼容的类型

types - 元组中的 OCaml 意外类型不匹配

scala - Scala 类型系统的哪些属性使其具有图灵完备性?