在Java 8中,提供了许多功能接口,例如UnaryOperator,BinaryOperator和Function等。
代码
UnaryOperator<Integer> uop1 = (Integer i) -> i * 10;
BinaryOperator<Integer> uop2 = (Integer i1, Integer i2) -> i1 * i2 * 10;
总是可以使用下面的Function来写
Function<Integer, Integer> f1 = (Integer i) -> i * 10;
BiFunction<Integer, Integer, Integer> f2 = (Integer i1, Integer i2) -> i1 * i2 * 10;
那么,这些操作员界面的用途是什么? 他们实现的功能是否与使用Function有所不同?
答案 0 :(得分:4)
为您提供方便。您可以写BiFunction<Integer, Integer, Integer>
而不用写BinaryOperator<Integer>
来代替。另一个好处是:您可以确保为您提供的函数接受一个或两个相同类型的参数,并在不进行过多编写的情况下准确返回该类型。
此外,由于BinaryOperator<T>
的性质,在其中放置minBy
和maxBy
之类的东西更有意义,而在{{ 1}}。由于给定的参数具有相同的类型,并且确保返回类型也相同,因此比较器可以轻松应用...非常方便。
答案 1 :(得分:2)
功能接口应尽可能专用。
拥有
Function<Integer, Integer> f1 = (Integer i) -> i * 10;
代替:
UnaryOperator<Integer> uop1 = (Integer i) -> i * 10;
实际上是一种代码气味(为此也有Sonar Rule squid:S4276
)。
这样做的简单原因是,创建这些接口是为了避免在只有一个接口的情况下n
次传递不必要的类型参数。
public interface UnaryOperator<T> extends Function<T, T>
因此,编写Function<T, T>
只是更长而且不必要的。
谈论诸如IntConsumer
与Consumer<Integer>
或DoubleToIntFunction
与Function<Double, Integer>
之类的其他界面,其中第二个选项可能会导致不必要的自动装箱并降低性能。
这就是为什么使用更具体,更适当的界面可以使您的代码看起来更整洁,并使您远离意外。
答案 2 :(得分:1)
是的,它们在功能上是相同的。他们甚至扩展了您正在讨论的类,并使用相同的SAM。 UnaryOperator
和BinaryOperator
接口仅定义静态方法。
public interface UnaryOperator<T> extends Function<T, T>
public interface BinaryOperator<T> extends BiFunction<T,T,T>
为了简洁起见,它们只是在那儿。为什么一次只能指定2到3次类型参数?
答案 3 :(得分:0)
UnaryOperator
和BinaryOperator
是Function
和BiFunction
的快捷方式。我认为它们也可能带有不同的含义,一个操作和一个函数可能具有不同的解释,具体取决于您的上下文,这实际上是出于代码可读性而不是出于技术原因。