Я использую следующие тестовые примеры для проверки 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 Простите, я запутался. Тогда как понять "Function <TestFunc, String> func = TestFunc :: nonStaticFunc1;" . Я получил ссылку на нестатический метод без экземпляра.




Это ужасно неправильно.
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), это Т параметр или вызывающий?
Кстати, вроде бы мы хотим сослаться на void func(void). Мы должны заменить void на Void.
TestFunc::nonStaticFunc1 и this::nonStaticFunc1 - это ссылки на методы. Я не понимаю, что вы имеете в виду под TestFunc::nonStaticFunc1.apply(para) или this::nonStaticFunc1.apply(para). Если вы еще не знакомы со ссылками на методы, то сначала используйте лямбда. Если лямбда тоже не знакома, попробуйте классическую инъекцию объекта new. Я снова отредактировал код, пытаясь прояснить, что на этот раз есть только два объекта TestFunc, и изменил принцип работы fun2 (чтобы вместо этого использовать параметр)
@Shark, если вы хотите, чтобы возвращаемый тип был void, вы должны использовать интерфейс с соответствующей функциональной сигнатурой, например. Runnable без аргументов, Consumer для одного аргумента или BiConsumer для двух аргументов.
@Holger Большое спасибо. Я понял это. Я немного запутался в пустоте. Теперь R Function <T, R>.apply(T) меня смущает. Основываясь на приведенном выше коде Nin, T иногда передается как параметр, иногда как вызывающий.
@Shark Я полагаю, вы имеете в виду термин «приемник». Когда у вас есть вызов метода a.method(b, c), тогда a является получателем вызова метода, а b и c - аргументами параметров, но все выражение вызова - это функционировать надa, b и c. Следовательно, вы можете выразить функцию с тремя параметрами, оценка которых будет выполнять вызов метода для ее первого аргумента, передавая два других в качестве аргументов параметра метода.
Так что с функциональной точки зрения a не особенный. Но это с точки зрения ООП, и именно поэтому у вас есть выбор: использовать TypeOfA::method для выражения функции, которая будет иметь получатель в качестве первого аргумента, за которым следуют все аргументы параметров метода, или использовать object::method, чтобы указать предварительный связанного объекта-получателя и получить функцию, имеющую только аргументы параметра метода.
@Holger Ваш ответ великолепен. Это именно то, что меня смущает. Я плохо говорю по-английски, но вы, ребята, такие добрые, еще раз спасибо!
Есть ли причина, по которой методы не статичны? Чтобы обратиться к нестатическому методу, вам понадобится экземпляр класса.