我有很多地方有 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/