apply()方法在Java中如何工作?
关于UnaryOperator功能接口,我已经阅读了文档,上面写着
@FunctionalInterface
public interface UnaryOperator<T> extends Function<T,T>
表示对单个操作数的操作,该操作产生与其操作数相同类型的结果。对于操作数和结果为相同类型的情况,这是对Function的专门化。
这是一个功能接口,其功能方法为Function.apply(Object)
。
什么是功能方法?
我有以下实现UnaryOperator接口的类。
public class Uppercase implements UnaryOperator<String> {
@Override
public String apply(String s) {
return s.trim().toUpperCase();
}
}
在方法调用中,
new Stream().map(new Uppercase())
它将任何输入流转换为大写。我的问题是,大写类中的apply()
方法是否会自动调用? (是toString()
方法自动调用println()
方法吗?)
如果不显式调用apply()
方法,我将找不到任何示例。因此,请帮助我了解这里发生的情况。
答案 0 :(得分:2)
是的,就像toString()
函数在println()
函数中调用一样。 println()
接受所有对象,因此默认情况下,toString()
继承自java.lang.Object
类以及Stream
类的map()
函数接受java.util.function.Function
类型的对象您完全可以通过Uppercase
类来实现它。
当涉及功能接口时,功能接口不仅是用@FunctionalInterface
注释修饰的接口。功能接口只能有一个实例方法。虽然可以有许多static
和default
方法。引入这些接口是为了与Java 8的新语法类型一起使用,这些语法类型称为 Lambda Expressions 。否则,这只是一个接口。
如果需要,您的解决方案可实现这种方式,创建一个匿名内部类;
new Stream().map(new Function() {
@Override
public String apply(String s) {
return s.trim().toUpperCase();
}
});
无需声明像Uppercase
这样的单独的具体类。使用lambda表达式,您可以像这样缩短代码;
new Stream().map(s -> s.trim().toUpperCase());
这是功能接口的功能方法的用法。仅当只有一种实例方法时,这才可能。无需像您一样实现单独的类。
答案 1 :(得分:1)
大写类中的apply()方法是否会自动调用?
在map
中实现的Stream
方法负责调用您创建的apply
的{{1}}方法。
注意:Function
实现Uppercase
扩展了UnaryOperator<T>
,这是您定义的Function<T, T>
实现的调用。
答案 2 :(得分:1)
它将任何输入流转换为大写。我的问题是 大写类中的apply()方法会自动调用吗?
实际上,这是在其上调用Stream.map()
的{{1}}实现的角色,当调用apply()
时,您将永远不会这样做。
抽象类Stream.map()
做到了:
ReferencePipeline
在Stream中定义的 @SuppressWarnings("unchecked")
public final <R> Stream<R> map(Function<? super P_OUT, ? extends R> mapper) {
Objects.requireNonNull(mapper);
return new StatelessOp<P_OUT, R>(this, StreamShape.REFERENCE,
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<P_OUT> opWrapSink(int flags, Sink<R> sink) {
return new Sink.ChainedReference<P_OUT, R>(sink) {
@Override
public void accept(P_OUT u) {
downstream.accept(mapper.apply(u)); // HERE
}
};
}
};
}
被声明为:
map()
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
期望Stream.map()
,并通过传递Function
,您将提供所有必需的信息。
在没有显式调用apply()方法的情况下,我找不到任何示例。 因此,请帮助我了解这里发生的情况。
通常,您不直接实现功能接口,而是传递一个lambda,因为它更直接:
UnaryOperator
答案 3 :(得分:0)
在计算机科学中,Apply是将函数应用于参数的函数。
这对Java可能是新的,但在函数式编程中很常见。 该对象可以视为具有应用方法的函数。因此,当创建新对象时,apply方法将与传递的参数一起执行。
弗拉德·古迪姆(Vlad Gudim)的回答已详细说明:https://stackoverflow.com/a/9738862/3812323
这是用于scala的,但在功能范例中成立。