Це взагалі можливо?
Відповіді:
якщо ви маєте на увазі анонімну функцію і використовуєте версію Java перед Java 8, то одним словом, ні. ( Прочитайте про лямбда-вирази, якщо ви використовуєте Java 8+ )
Однак ви можете реалізувати інтерфейс з такою функцією:
Comparator<String> c = new Comparator<String>() {
int compare(String s, String s2) { ... }
};
і ви можете використовувати це з внутрішніми класами, щоб отримати майже анонімну функцію :)
Ось приклад анонімного внутрішнього класу.
System.out.println(new Object() {
@Override public String toString() {
return "Hello world!";
}
}); // prints "Hello world!"
Це не дуже корисно, але воно показує, як створити екземпляр анонімного внутрішнього класу that 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
довжина).
EventListener
(під) реалізації в середньому додатку Swing.
Linked
бічну панель, тому я роблю все можливе, щоб нею скористатися.
З введенням лямбда-виразу в Java 8 тепер ви можете мати анонімні методи.
Скажімо, у мене є клас, Alpha
і я хочу відфільтрувати Alpha
s за певною умовою. Для цього ви можете використовувати a 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 ви можете:
filter(alpha -> alpha.centauri > 1);
Для отримання більш детальної інформації див. Посібник Lambda Expressions
Анонімні внутрішні класи, що реалізують або розширюють інтерфейс існуючого типу, були зроблені в інших відповідях, хоча варто зауважити, що можуть бути реалізовані кілька методів (часто, наприклад, з подіями в стилі 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
» місцеві жителі? )
node
слід оголосити final
тут.
cur
.
"Node" +
щоб зробити другий метод необхідним). / У мене немає імені. Можливо, я міг би створити запитання про "опитування" (CW), і проголосувати його забуваючи.
Так, якщо ви використовуєте останню 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.
Дужки, які містять аргументи конструктора, як і звичайний вираз створення екземпляра класу. Примітка: Коли ви реалізуєте інтерфейс, конструктор відсутній, тому ви використовуєте порожню пару дужок, як у цьому прикладі.
Тіло, яке є тілом оголошення класу. Більш конкретно, в тілі декларації методів дозволені, а оператори - ні.