有关Java8中的功能接口的问题

时间:2019-06-27 04:02:07

标签: java function lambda interface unary-operator

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()方法,我将找不到任何示例。因此,请帮助我了解这里发生的情况。

4 个答案:

答案 0 :(得分:2)

是的,就像toString()函数在println()函数中调用一样。 println()接受所有对象,因此默认情况下,toString()继承自java.lang.Object类以及Stream类的map()函数接受java.util.function.Function类型的对象您完全可以通过Uppercase类来实现它。

当涉及功能接口时,功能接口不仅是用@FunctionalInterface注释修饰的接口。功能接口只能有一个实例方法。虽然可以有许多staticdefault方法。引入这些接口是为了与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的,但在功能范例中成立。