Как написать анонимную функцию в Java?

Возможно ли это?

Ответ 1

если вы имеете в виду анонимную функцию, и используете версию Java до Java 8,, то словом, нет. (Читайте о лямбда-выражениях, если вы используете Java 8+)

Однако вы можете реализовать интерфейс с такой функцией:

Comparator<String> c = new Comparator<String>() {
    int compare(String s, String s2) { ... }
};

и вы можете использовать это с внутренними классами, чтобы получить почти анонимную функцию:)

Ответ 2

Вот пример анонимного внутреннего класса.

System.out.println(new Object() {
    @Override public String toString() {
        return "Hello world!";
    }
}); // prints "Hello world!"

Это не очень полезно, как есть, но показывает, как создать экземпляр анонимного внутреннего класса, который extends Object и @Override его метод toString().

См. также


Анонимные внутренние классы очень удобны, когда вам нужно реализовать interface, который не может быть сильно повторно использован (и, следовательно, не стоит рефакторинг для своего собственного именованного класса). Поучительный пример - использование java.util.Comparator<T> для сортировки.

Вот пример того, как вы можете сортировать String[] на основе String.length().

import java.util.*;
//...

String[] arr = { "xxx", "cd", "ab", "z" };
Arrays.sort(arr, new Comparator<String>() {
    @Override public int compare(String s1, String s2) {
        return s1.length() - s2.length();
    }           
});
System.out.println(Arrays.toString(arr));
// prints "[z, cd, ab, xxx]"

Обратите внимание на используемый здесь метод сравнения за вычетом. Следует сказать, что эта техника нарушена в целом: она применима только тогда, когда вы можете гарантировать, что она не будет переполняться (например, с длиной String).

См. также

Ответ 3

С введением лямбда-выражения в Java 8 теперь можно использовать анонимные методы.

Скажем, у меня есть класс Alpha, и я хочу фильтровать Alpha в определенном состоянии. Для этого вы можете использовать Predicate<Alpha>. Это функциональный интерфейс, который имеет метод test, который принимает Alpha и возвращает a boolean.

Предполагая, что метод фильтра имеет эту подпись:

List<Alpha> filter(Predicate<Alpha> filterPredicate)

Со старым решением анонимного класса вам нужно что-то вроде:

filter(new Predicate<Alpha>() {
   boolean test(Alpha alpha) {
      return alpha.centauri > 1;
   }
});

С помощью Java 8 lambdas вы можете:

filter(alpha -> alpha.centauri > 1);

Более подробную информацию см. в Учебное пособие по лямбда-выражениям

Ответ 4

Анонимные внутренние классы, реализующие или расширяющие интерфейс существующего типа, были выполнены в других ответах, хотя стоит отметить, что могут быть реализованы несколько методов (часто с событиями в стиле JavaBean, например).

Мало признанной особенностью является то, что хотя анонимные внутренние классы не имеют имени, у них есть тип. К интерфейсу могут быть добавлены новые методы. Эти методы могут быть вызваны только в ограниченных случаях. В основном непосредственно на самом выражении new и внутри класса (включая инициализаторы экземпляра). Это может запутать новичков, но это может быть "интересно" для рекурсии.

private static String pretty(Node node) {
    return "Node: " + new Object() {
        String print(Node cur) {
            return cur.isTerminal() ?
                cur.name() :
                ("("+print(cur.left())+":"+print(cur.right())+")");
        }
    }.print(node);
}

(я изначально написал это, используя node, а не cur в методе print. Скажите НЕТ для захвата "неявно final" locals?)

Ответ 5

Да, если вы используете последнюю версию Java версии 8. Java8 позволяет определять анонимные функции, которые были невозможны в предыдущих версиях.

Давайте возьмем пример из java docs, чтобы узнать, как мы можем объявлять анонимные функции, классы

В следующем примере HelloWorldAnonymousClasses использует анонимный классов в операторах инициализации локальных переменных frenchGreeting и spanishGreeting, но использует локальный класс для инициализация переменной englishGreeting:

public class HelloWorldAnonymousClasses {

    interface HelloWorld {
        public void greet();
        public void greetSomeone(String someone);
    }

    public void sayHello() {

        class EnglishGreeting implements HelloWorld {
            String name = "world";
            public void greet() {
                greetSomeone("world");
            }
            public void greetSomeone(String someone) {
                name = someone;
                System.out.println("Hello " + name);
            }
        }

        HelloWorld englishGreeting = new EnglishGreeting();

        HelloWorld frenchGreeting = new HelloWorld() {
            String name = "tout le monde";
            public void greet() {
                greetSomeone("tout le monde");
            }
            public void greetSomeone(String someone) {
                name = someone;
                System.out.println("Salut " + name);
            }
        };

        HelloWorld spanishGreeting = new HelloWorld() {
            String name = "mundo";
            public void greet() {
                greetSomeone("mundo");
            }
            public void greetSomeone(String someone) {
                name = someone;
                System.out.println("Hola, " + name);
            }
        };
        englishGreeting.greet();
        frenchGreeting.greetSomeone("Fred");
        spanishGreeting.greet();
    }

    public static void main(String... args) {
        HelloWorldAnonymousClasses myApp =
            new HelloWorldAnonymousClasses();
        myApp.sayHello();
    }            
}

Синтаксис анонимных классов

Рассмотрим экземпляр объекта frenchGreeting:

    HelloWorld frenchGreeting = new HelloWorld() {
        String name = "tout le monde";
        public void greet() {
            greetSomeone("tout le monde");
        }
        public void greetSomeone(String someone) {
            name = someone;
            System.out.println("Salut " + name);
        }
    };

Выражение анонимного класса состоит из следующего:

  • Оператор new
  • Имя интерфейса для реализации или расширяемый класс. В этом Например, анонимный класс реализует интерфейс HelloWorld.

  • Скобки, содержащие аргументы конструктору, как и выражение выражения экземпляра нормального класса. Примечание. Когда вы реализуете интерфейса нет конструктора, поэтому вы используете пустую пару круглые скобки, как в этом примере.

  • Тело, являющееся телом декларации класса. Более конкретно, в body, объявления метода разрешены, но не являются инструкциями.