Возможно ли это?
Как написать анонимную функцию в 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, объявления метода разрешены, но не являются инструкциями.