Функция в Java8, как получить ссылку на Cls :: func (Cls cls), возвращает Object;

Я использую следующие тестовые примеры для проверки java.util.function.Function.

public class TestFunc {

  public String nonStaticFunc1 () {
    return "nonStaticAndPara of fun1";
  }
  public String nonStaticFunc1 (TestFunc tf) {
    return "nonStaticWithPara of fun1";
  }
  public String nonStaticFunc2 (TestFunc tf) {
    return "nonStaticWithPara of fun2";
  }
  @Test
  public void testFunc () {
    Function<TestFunc, String> func = TestFunc::nonStaticFunc1;
    System.out.println(func.apply(new TestFunc()));
    // Cannot make a static reference to the non-static method nonStaticFunc2(TestFunc) from the type TestFunc
    // Function<TestFunc, String> func2 = TestFunc::nonStaticFunc2;
  }
}
/* OUTPUT
 nonStaticAndPara of fun1
*///:~

Функция, всегда соответствующая TestFunc :: nonStaticFunc1 (void), возвращает String; Я проверил исходный код функции:

public interface Function<T, R> {
  R apply(T t);
}

Кажется, когда параметр функции пуст, java автоматически импортирует в него объект класса. Тогда как я могу получить TestFunc :: nonStaticFunc1 (TestFunc)? Заранее спасибо.

Есть ли причина, по которой методы не статичны? Чтобы обратиться к нестатическому методу, вам понадобится экземпляр класса.

Bubletan 01.08.2018 04:20

@Bubletan Простите, я запутался. Тогда как понять "Function <TestFunc, String> func = TestFunc :: nonStaticFunc1;" . Я получил ссылку на нестатический метод без экземпляра.

Shark 01.08.2018 04:49
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
2
79
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это ужасно неправильно.

java automatically import a class object

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

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

import java.util.function.Function;

public class TestFunc {
    private final String name;

    public String getName() {
        return name;
    }

    public TestFunc(String name) {
        this.name = name;
    }

    public String nonStaticFunc1() {
        return "nonStaticAndPara of fun1 (no further parameter): " + this.name;
    }

    public String nonStaticFunc1(TestFunc parameter) {
        // parameter is received but ignored
        return "nonStaticWithPara of fun1 (parameter is received but ignored): " + this.name;
    }

    public String nonStaticFunc2(TestFunc parameter) {
        // parameter is received and used
        return "nonStaticWithPara of fun2 (parameter is received and used): " + parameter.getName();
    }

    public void testFunc(TestFunc parameter) {
        Function<TestFunc, String> func;

        func = TestFunc::nonStaticFunc1;
        System.out.println(func.apply(parameter));

        func = testFunc -> testFunc.nonStaticFunc1();
        System.out.println(func.apply(parameter));
        // TestFunc::nonStaticFunc1
        // means
        // calling nonStaticFunc1 from the parameter as in `apply(parameter)`

        func = this::nonStaticFunc1;
        System.out.println(func.apply(parameter));

        func = testFunc -> this.nonStaticFunc1(testFunc);
        System.out.println(func.apply(parameter));
        // this::nonStaticFunc1
        // means
        // this.nonStaticFunc1(testFunc)

        // similarly func2
        func = this::nonStaticFunc2;
        System.out.println(func.apply(parameter));

        func = testFunc -> this.nonStaticFunc2(testFunc);
        System.out.println(func.apply(parameter));

        // func = TestFunc::nonStaticFunc2; // doesn't make sense, there's no such thing as parameter of the parameter
    }

    public static void main(String[] args) {
        TestFunc parameter = new TestFunc("param");
        TestFunc caller = new TestFunc("caller");
        caller.testFunc(parameter);
    }
}

Выход:

nonStaticAndPara of fun1 (no further parameter): param
nonStaticAndPara of fun1 (no further parameter): param
nonStaticWithPara of fun1 (parameter is received but ignored): caller
nonStaticWithPara of fun1 (parameter is received but ignored): caller
nonStaticWithPara of fun2 (parameter is received and used): param
nonStaticWithPara of fun2 (parameter is received and used): param

Я оставил несколько комментариев в коде в качестве примечаний для объяснения некоторой фундаментальной логики. Надеюсь, вы знакомы с лямбдой.

Обновлено: уменьшить количество объектов в образце кода EDIT2: изменить способ работы nonStaticFunc2 (теперь вместо этого используется параметр)

Большое спасибо за ваш код и время. Но я все еще в замешательстве. TestFunc::nonStaticFunc1.apply(para) приравнивается к para.nonStaticFunc1(), но this::nonStaticFunc1.apply(para) приравнивается к this.nonStaticFunc1(para). Тогда как понять на R Function<T, R>.apply(T), это Т параметр или вызывающий?

Shark 01.08.2018 05:43

Кстати, вроде бы мы хотим сослаться на void func(void). Мы должны заменить void на Void.

Shark 01.08.2018 05:44
TestFunc::nonStaticFunc1 и this::nonStaticFunc1 - это ссылки на методы. Я не понимаю, что вы имеете в виду под TestFunc::nonStaticFunc1.apply(para) или this::nonStaticFunc1.apply(para). Если вы еще не знакомы со ссылками на методы, то сначала используйте лямбда. Если лямбда тоже не знакома, попробуйте классическую инъекцию объекта new. Я снова отредактировал код, пытаясь прояснить, что на этот раз есть только два объекта TestFunc, и изменил принцип работы fun2 (чтобы вместо этого использовать параметр)
Nin 01.08.2018 06:15

@Shark, если вы хотите, чтобы возвращаемый тип был void, вы должны использовать интерфейс с соответствующей функциональной сигнатурой, например. Runnable без аргументов, Consumer для одного аргумента или BiConsumer для двух аргументов.

Holger 01.08.2018 15:32

@Holger Большое спасибо. Я понял это. Я немного запутался в пустоте. Теперь R Function <T, R>.apply(T) меня смущает. Основываясь на приведенном выше коде Nin, T иногда передается как параметр, иногда как вызывающий.

Shark 02.08.2018 04:31

@Shark Я полагаю, вы имеете в виду термин «приемник». Когда у вас есть вызов метода a.method(b, c), тогда a является получателем вызова метода, а b и c - аргументами параметров, но все выражение вызова - это функционировать надa, b и c. Следовательно, вы можете выразить функцию с тремя параметрами, оценка которых будет выполнять вызов метода для ее первого аргумента, передавая два других в качестве аргументов параметра метода.

Holger 02.08.2018 12:30

Так что с функциональной точки зрения a не особенный. Но это с точки зрения ООП, и именно поэтому у вас есть выбор: использовать TypeOfA::method для выражения функции, которая будет иметь получатель в качестве первого аргумента, за которым следуют все аргументы параметров метода, или использовать object::method, чтобы указать предварительный связанного объекта-получателя и получить функцию, имеющую только аргументы параметра метода.

Holger 02.08.2018 12:32

@Holger Ваш ответ великолепен. Это именно то, что меня смущает. Я плохо говорю по-английски, но вы, ребята, такие добрые, еще раз спасибо!

Shark 03.08.2018 04:24

Другие вопросы по теме