Вопрос касательно функционального интерфейса в Java8 - PullRequest
1 голос
/ 27 июня 2019

Как метод 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 ]

2 голосов
/ 27 июня 2019

Да, это точно так же, как функция toString() вызывается в функции println().println() принимает все объекты, поэтому по умолчанию toString() наследуется от класса java.lang.Object, а функция map() класса Stream принимает объекты типа java.util.function.Function, которые вы точно выполнили, реализовав его с классом Uppercase.

Когда речь идет о функциональных интерфейсах, функциональный интерфейс - это не просто интерфейс, украшенный аннотацией @FunctionalInterface.Функциональный интерфейс только может иметь один метод экземпляра.Может иметь много методов static и default.Эти интерфейсы в основном введены для работы с новым синтаксическим типом Java 8 под названием Лямбда-выражения .В противном случае это просто интерфейс.

Ваше решение, если хотите, реализует подобное, создавая анонимный внутренний класс;

new Stream().map(new Function() {

    @Override
    public String apply(String s) {
        return s.trim().toUpperCase();
    }
});

Нет необходимости объявлять отдельный конкретный класс, такой как Uppercase.С помощью лямбда-выражения вы можете сократить код следующим образом:

new Stream().map(s -> s.trim().toUpperCase());

Это использование функциональных методов функциональных интерфейсов.Это возможно только при наличии только одного метода экземпляра .Нет необходимости реализовывать отдельный класс, как вы.

1 голос
/ 27 июня 2019

Конвертирует любой входной поток в верхний регистр.Мой вопрос заключается в том, вызывается ли метод apply () в классе Uppercase автоматически?

Действительно, в этом заключается роль Stream.map() реализации вызова apply(), вы никогда этого не сделаете, когдаStream.map() вызывается.

Абстрактный класс 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 
                }
            };
        }
    };
}

map(), определенный в Stream, объявляется как:

<R> Stream<R> map(Function<? super T, ? extends R> mapper);

Stream.map() ожидает Function и, передав UnaryOperator, вы предоставляете все, что требуется.

Я не смог найти ни одного примера без явного вызова метода apply ().Поэтому, пожалуйста, помогите мне понять, что здесь произошло.

Как правило, вы не реализуете непосредственно функциональный интерфейс, но передаете лямбду, поскольку это более просто:

new Stream().map(s->s.trim().toUpperCase())....
1 голос
/ 27 июня 2019

автоматически ли вызывается метод apply () в классе Uppercase?

Метод map, реализованный в Stream, отвечает за вызов метода apply созданного вами Function.

Примечание : Uppercase реализует UnaryOperator<T> extends Function<T, T>, где называется реализация apply, определенная вами.

0 голосов
/ 27 июня 2019

В информатике Apply - это функция, которая применяет функции к аргументам.

Это может быть новым для Java, но это часто встречается в функциональном программировании. Объект можно рассматривать как функцию, к которой применен метод. Поэтому, когда создается новый объект, метод apply будет выполняться с переданными аргументами.

Подробно разъяснил ответ Влад Гудим: https://stackoverflow.com/a/9738862/3812323

Это для скалы, но в функциональной парадигме это верно.

...