关于 Java8 中功能接口的问题
Question regarding functional interface in Java8
apply() 方法在 Java 中如何工作?
关于UnaryOperator函数式接口,我看了文档,上面写着
@FunctionalInterface
public interface UnaryOperator<T> extends Function<T,T>
表示对单个操作数的操作,产生与其操作数类型相同的结果。这是 Function 的特化,适用于操作数和结果属于同一类型的情况。
这是一个函数式接口,它的函数式方法是Function.apply(Object)
.
函数方法是什么?
我有以下 class 实现了 UnaryOperator 接口。
public class Uppercase implements UnaryOperator<String> {
@Override
public String apply(String s) {
return s.trim().toUpperCase();
}
}
在方法调用中,
new Stream().map(new Uppercase())
它将任何输入流转换为大写。我的问题是,是否会自动调用 Uppercase class 中的 apply()
方法? (是不是像toString()
方法被println()
方法自动调用了?)
如果不显式调用 apply()
方法,我找不到任何示例。所以请帮助我了解这里发生了什么。
does the apply() method in Uppercase class get called automatically?
Stream
中实现的map
方法负责调用您创建的Function
的apply
方法。
注意: Uppercase
implements UnaryOperator<T>
extends Function<T, T>
也就是你定义的apply
的实现被调用的地方.
It converts whatever input stream into uppercase. My question is, does
the apply() method in Uppercase class get called automatically?
确实是Stream.map()
实现调用apply()
的作用,所以当Stream.map()
被调用时你永远不会这样做。
摘要 class ReferencePipeline
这样做:
@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
}
};
}
};
}
Stream 中定义的 map()
声明为:
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
Stream.map()
期望 Function
并通过传递 UnaryOperator
您提供所有必需的。
I couldn't find any example without calling apply() method explicitly.
So please help me understand what happened here.
通常您不直接实现功能接口,而是传递一个 lambda,因为这样更直接:
new Stream().map(s->s.trim().toUpperCase())....
是的,它与 toString()
函数在 println()
函数中调用完全一样。 println()
接受所有对象,因此默认情况下 toString()
继承自 java.lang.Object
class 以及 Stream
class 的 map()
函数接受 java.util.function.Function
类型的对象,您使用 Uppercase
class 完全实现了它。
说到函数式接口,函数式接口不仅仅是一个用@FunctionalInterface
注解装饰的接口。功能接口只能有一个实例方法。虽然可以有许多 static
和 default
方法。这些接口基本上是为了与 Java 8 的新语法类型 Lambda Expressions 一起工作而引入的。否则这只是一个接口。
如果你愿意,你的解决方案可以这样实现,创建一个匿名内部 class;
new Stream().map(new Function() {
@Override
public String apply(String s) {
return s.trim().toUpperCase();
}
});
无需像 Uppercase
那样声明单独的具体 class。使用 lambda 表达式,您可以像这样缩短代码;
new Stream().map(s -> s.trim().toUpperCase());
这是函数式接口的函数式方法的用法。这只有在只有一个 实例方法 时才有可能。无需像您那样实施单独的 class。
In computer science, Apply is a function that applies functions to arguments.
这对 Java 来说可能是新的,但它在函数式编程中很常见。
该对象可以被视为具有 apply 方法的函数。所以当一个新的对象被创建时,apply 方法将被传递的参数执行。
Vlad Gudim 的回答有详细的解释:
它适用于 scala,但在函数范式中也适用。
apply() 方法在 Java 中如何工作?
关于UnaryOperator函数式接口,我看了文档,上面写着
@FunctionalInterface
public interface UnaryOperator<T> extends Function<T,T>
表示对单个操作数的操作,产生与其操作数类型相同的结果。这是 Function 的特化,适用于操作数和结果属于同一类型的情况。
这是一个函数式接口,它的函数式方法是Function.apply(Object)
.
函数方法是什么?
我有以下 class 实现了 UnaryOperator 接口。
public class Uppercase implements UnaryOperator<String> {
@Override
public String apply(String s) {
return s.trim().toUpperCase();
}
}
在方法调用中,
new Stream().map(new Uppercase())
它将任何输入流转换为大写。我的问题是,是否会自动调用 Uppercase class 中的 apply()
方法? (是不是像toString()
方法被println()
方法自动调用了?)
如果不显式调用 apply()
方法,我找不到任何示例。所以请帮助我了解这里发生了什么。
does the apply() method in Uppercase class get called automatically?
Stream
中实现的map
方法负责调用您创建的Function
的apply
方法。
注意: Uppercase
implements UnaryOperator<T>
extends Function<T, T>
也就是你定义的apply
的实现被调用的地方.
It converts whatever input stream into uppercase. My question is, does the apply() method in Uppercase class get called automatically?
确实是Stream.map()
实现调用apply()
的作用,所以当Stream.map()
被调用时你永远不会这样做。
摘要 class ReferencePipeline
这样做:
@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
}
};
}
};
}
Stream 中定义的 map()
声明为:
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
Stream.map()
期望 Function
并通过传递 UnaryOperator
您提供所有必需的。
I couldn't find any example without calling apply() method explicitly. So please help me understand what happened here.
通常您不直接实现功能接口,而是传递一个 lambda,因为这样更直接:
new Stream().map(s->s.trim().toUpperCase())....
是的,它与 toString()
函数在 println()
函数中调用完全一样。 println()
接受所有对象,因此默认情况下 toString()
继承自 java.lang.Object
class 以及 Stream
class 的 map()
函数接受 java.util.function.Function
类型的对象,您使用 Uppercase
class 完全实现了它。
说到函数式接口,函数式接口不仅仅是一个用@FunctionalInterface
注解装饰的接口。功能接口只能有一个实例方法。虽然可以有许多 static
和 default
方法。这些接口基本上是为了与 Java 8 的新语法类型 Lambda Expressions 一起工作而引入的。否则这只是一个接口。
如果你愿意,你的解决方案可以这样实现,创建一个匿名内部 class;
new Stream().map(new Function() {
@Override
public String apply(String s) {
return s.trim().toUpperCase();
}
});
无需像 Uppercase
那样声明单独的具体 class。使用 lambda 表达式,您可以像这样缩短代码;
new Stream().map(s -> s.trim().toUpperCase());
这是函数式接口的函数式方法的用法。这只有在只有一个 实例方法 时才有可能。无需像您那样实施单独的 class。
In computer science, Apply is a function that applies functions to arguments.
这对 Java 来说可能是新的,但它在函数式编程中很常见。 该对象可以被视为具有 apply 方法的函数。所以当一个新的对象被创建时,apply 方法将被传递的参数执行。
Vlad Gudim 的回答有详细的解释:
它适用于 scala,但在函数范式中也适用。