Указатели на функции в Java

Я не эксперт в python, но вы могли бы попробовать: say

i = (1,2)

res = lambda i: (i[1],i[0])
print 'res(1, 2) = {0}'.format(res(1, 2)) 

выше дал бы o / p as:

res(1, 2) = (2,1)
146
задан Ben Lakey 2 July 2009 в 09:19
поделиться

9 ответов

Идиома Java для функциональности, подобной указателю на функцию, - это анонимный класс, реализующий интерфейс, например

Collections.sort(list, new Comparator<MyClass>(){
    public int compare(MyClass a, MyClass b)
    {
        // compare objects
    }
});

Обновление: вышеуказанное необходимо в версиях Java до Java 8. Теперь у нас есть гораздо более приятные альтернативы, а именно лямбды:

list.sort((a, b) -> a.isGreaterThan(b));

и ссылки на методы:

list.sort(MyClass::isGreaterThan);
125
ответ дан 23 November 2019 в 22:35
поделиться

Вы можете заменить указатель функции на интерфейс. Допустим, вы хотите просмотреть коллекцию и что-то сделать с каждым элементом.

public interface IFunction {
  public void execute(Object o);
}

Это интерфейс, который мы могли бы передать некоторым, скажем, CollectionUtils2.doFunc (Collection c, IFunction f).

public static void doFunc(Collection c, IFunction f) {
   for (Object o : c) {
      f.execute(o);
   }
}

В качестве примера скажем, что у нас есть набор чисел, и вы хотите добавить 1 к каждому элементу.

CollectionUtils2.doFunc(List numbers, new IFunction() {
    public void execute(Object o) {
       Integer anInt = (Integer) o;
       anInt++;
    }
});
64
ответ дан 23 November 2019 в 22:35
поделиться

Для достижения аналогичной функциональности вы можете использовать анонимные внутренние классы.

Если вы должны определить интерфейс Foo :

interface Foo {
    Object myFunc(Object arg);
}

Создайте метод bar , который получит в качестве аргумента «указатель на функцию»:

public void bar(Foo foo) {
    // .....
    Object object = foo.myFunc(argValue);
    // .....
}

Наконец, вызовите метод следующим образом:

bar(new Foo() {
    public Object myFunc(Object arg) {
        // Function code.
    }
}
8
ответ дан 23 November 2019 в 22:35
поделиться

Нет, в java функции не являются объектами первого класса. Вы можете сделать то же самое, реализуя класс обработчика - вот как обратные вызовы реализованы в Swing и т. Д.

Однако есть предложения по закрытию (официальное название того, о чем вы говорите) в будущих версиях java - В Javaworld есть интересная статья.

20
ответ дан 23 November 2019 в 22:35
поделиться

В Java такого нет. Вам нужно будет обернуть вашу функцию в какой-либо объект и передать ссылку на этот объект, чтобы передать ссылку на метод этого объекта.

Синтаксически это можно в определенной степени облегчить, используя анонимные классы, определенные в place или анонимные классы, определенные как переменные-члены класса.

Пример:

class MyComponent extends JPanel {
    private JButton button;
    public MyComponent() {
        button = new JButton("click me");
        button.addActionListener(buttonAction);
        add(button);
    }

    private ActionListener buttonAction = new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            // handle the event...
            // note how the handler instance can access 
            // members of the surrounding class
            button.setText("you clicked me");
        }
    }
}
5
ответ дан 23 November 2019 в 22:35
поделиться

Здесь вспоминается Казнь Стива Йегге в Царстве существительных . По сути, в нем говорится, что Java нужен объект для каждого действия, и поэтому в нем нет сущностей «только для глаголов», таких как указатели на функции.

15
ответ дан 23 November 2019 в 22:35
поделиться

Проверьте замыкания, как они реализованы в библиотеке lambdaj. На самом деле они ведут себя очень похоже на делегатов C #:

http://code.google.com/p/lambdaj/wiki/Closures

2
ответ дан 23 November 2019 в 22:35
поделиться

Я внедрил поддержку обратного вызова / делегата в Java с использованием отражения. Детали и рабочий источник доступны на моем сайте .

Как это работает

У нас есть принципиальный класс с именем Callback с вложенным классом с именем Carms. API, который нуждается в обратном вызове, возьмут объект обратного вызова в качестве параметра, и, если необходимо, создайте обратный вызов. WithParms как переменная метода. Поскольку многие из приложений этого объекта будут рекурсивные, это работает очень чисто.

С исполнением до сих пор является высоким приоритетом для меня, я не хотел, чтобы создать массив накладных объектов для удержания параметров для каждого вызова - в конце концов в рамках большой структуры данных могут быть тысячи элементов, а в Сценарий обработки сообщений мы могли бы оказаться обработки тысяч структур данных в секунду.

Для использования Threadsafe массив параметров должен быть однозначно существует для каждого вызова метода API, а для эффективности того же следует использовать для каждого вызова обратного вызова; Мне нужен был второй объект, который будет дешевым для создания, чтобы связать обратный вызов с массивом параметров для вызова. Но в некоторых сценариях INSOOKE уже будет иметь массив параметра по другим причинам. По этим двум причинам массив параметров не принадлежал в объекте обратного вызова. Также выбор вызова (передача параметров как массив или в качестве отдельных объектов) принадлежит в руках API, используя обратный вызов, позволяющий использовать то, что вызов которого лучше всего подходит для его внутренней работы.

Вложенные классы с Apparms, затем являются необязательными и служат двумя целями, он содержит массив объекта параметра, необходимый для вызовов обратного вызова, и он предоставляет 10 методов перегрузки (с от 1 до 10), которые загружают параметр массив, а затем вызвать цель обратного вызова.

3
ответ дан 23 November 2019 в 22:35
поделиться

Для этого вы можете использовать отражение.

Передайте в качестве параметра объект и имя метода (в виде строки), а затем вызовите метод. Например:

Object methodCaller(Object theObject, String methodName) {
   return theObject.getClass().getMethod(methodName).invoke(theObject);
   // Catch the exceptions
}

А затем используйте его, как в:

String theDescription = methodCaller(object1, "toString");
Class theClass = methodCaller(object2, "getClass");

Конечно, проверьте все исключения и добавьте необходимые преобразования.

41
ответ дан 23 November 2019 в 22:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: