我在很多地方都有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);
}
这失败了
错误:(93,39)java:不兼容的类型:不存在类型为V的实例,因此java.util.function.Function符合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;
}
}
我现在虽然收到此警告(将Javac 1.8.0_25与--Xlint:all结合使用)
警告:[FooTransformer中的[overloads] andThen(FooTransformer)is
与andThen(Function)可能存在歧义
功能
默认FooTransformer andThen(FooTransformer之后){
^
其中V,R,T是类型变量:
V扩展在方法andThen中声明的对象(函数扩展V>)
R扩展接口函数中声明的对象
T扩展了接口函数中声明的对象
我真正想要的是
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
参数类型重载了方法,则对于有人尝试用实现两个interface
的具体类型调用任一方法的情况,可能会造成歧义。这在这里不适用,因为一种参数类型是另一种参数的子类型,因此它永远不会模棱两可,但是javac
似乎不够聪明,无法识别这一点。因此,您可以与javac
开发人员进行讨论,希望以后的版本不发出警告,但是,在该方法中添加@SuppressWarnings("overloads")
是更简单的解决方案……请注意,我更改了实现,以不将
Function.super.andThen
的结果包装到FooTransformer
中。尽管方法引用是将任意接口实例转换为另一个接口的一种好方法,但我认为,当已知实际实现且在这种情况下如此简单时,应避免将一个函数包装到另一个函数中的开销。请注意,您可以考虑让
FooTransformer
扩展UnaryOperator<Foo>
,这是Function<Foo,Foo>
的子接口。所以一切都像以前一样工作,但是您可以选择将FooTransformer
的实例与List.replaceAll
或Stream.iterate
或AtomicReference.updateAndGet
一起使用…