Как я могу написать анонимную функцию в Java? - PullRequest
83 голосов
/ 03 мая 2010

Возможно ли это вообще?

Ответы [ 5 ]

76 голосов
/ 03 мая 2010

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

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

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

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

43 голосов
/ 03 мая 2010

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

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 длинами).

Смотри также

11 голосов
/ 03 июля 2014

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

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

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

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

При старом решении анонимного класса вам понадобится что-то вроде:

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

С лямбдами Java 8 вы можете:

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

Для получения более подробной информации см. Учебник Lambda Expressions

9 голосов
/ 03 мая 2010

Анонимные внутренние классы, реализующие или расширяющие интерфейс существующего типа, были сделаны в других ответах, хотя стоит отметить, что можно реализовать несколько методов (например, часто с событиями в стиле 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" локальных?

0 голосов
/ 23 сентября 2015

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

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

В следующем примере 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.

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

  • Тело, которое является телом объявления класса. Более конкретно, в Тело, объявления методов допускаются, а операторы - нет.

...