Czy to w ogóle możliwe?
java
anonymous-function
aarona
źródło
źródło
Odpowiedzi:
jeśli masz na myśli funkcję anonimową i używasz wersji Javy wcześniejszej niż Java 8, to jednym słowem nie. ( Przeczytaj o wyrażeniach lambda, jeśli używasz Java 8+ )
Możesz jednak zaimplementować interfejs z taką funkcją:
Comparator<String> c = new Comparator<String>() { int compare(String s, String s2) { ... } };
i możesz użyć tego z klasami wewnętrznymi, aby uzyskać prawie anonimową funkcję :)
źródło
Oto przykład anonimowej klasy wewnętrznej.
System.out.println(new Object() { @Override public String toString() { return "Hello world!"; } }); // prints "Hello world!"
Nie jest to zbyt użyteczne, ale pokazuje, jak utworzyć instancję anonimowej klasy wewnętrznej that
extends Object
i@Override
jejtoString()
metodę.Zobacz też
Anonimowe klasy wewnętrzne są bardzo przydatne, gdy trzeba zaimplementować klasę,
interface
która może nie nadawać się do wielokrotnego użytku (i dlatego nie jest warta refaktoryzacji do własnej nazwanej klasy). Pouczającym przykładem jest użycie zwyczajujava.util.Comparator<T>
do sortowania.Oto przykład, jak możesz sortować pliki na
String[]
podstawieString.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]"
Zwróć uwagę na zastosowaną tutaj sztuczkę porównania przez odejmowanie. Należy powiedzieć, że ta technika jest ogólnie zepsuta: ma zastosowanie tylko wtedy, gdy można zagwarantować, że nie będzie się przepełniać (tak jest w przypadku
String
długości).Zobacz też
źródło
EventListener
(pod) implementacje w przeciętnej aplikacji Swing.Linked
pasek boczny, więc staram się jak najlepiej go wykorzystać.Wraz z wprowadzeniem wyrażenia lambda w Javie 8 można teraz mieć metody anonimowe.
Załóżmy, że mam klasę
Alpha
i chcę filtrować jeAlpha
według określonego warunku. Aby to zrobić, możesz użyć plikuPredicate<Alpha>
. To jest funkcjonalny interfejs, który ma metodę,test
która akceptujeAlpha
i zwracaboolean
.Zakładając, że metoda filtru ma taki podpis:
List<Alpha> filter(Predicate<Alpha> filterPredicate)
W przypadku starego rozwiązania klasy anonimowej potrzebujesz czegoś takiego:
filter(new Predicate<Alpha>() { boolean test(Alpha alpha) { return alpha.centauri > 1; } });
Z lambdami Java 8 możesz:
filter(alpha -> alpha.centauri > 1);
Aby uzyskać bardziej szczegółowe informacje, zobacz samouczek dotyczący wyrażeń lambda
źródło
Anonimowe klasy wewnętrzne implementujące lub rozszerzające interfejs istniejącego typu zostały wykonane w innych odpowiedziach, chociaż warto zauważyć, że można zaimplementować wiele metod (często na przykład ze zdarzeniami w stylu JavaBean).
Trochę rozpoznawalną cechą jest to, że chociaż anonimowe klasy wewnętrzne nie mają nazwy, mają typ. Do interfejsu można dodać nowe metody. Metody te można wywoływać tylko w ograniczonych przypadkach. Głównie bezpośrednio w samym
new
wyrażeniu iw klasie (w tym inicjatory instancji). Może to zmylić początkujących, ale rekurencja może być „interesująca”.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); }
(Pierwotnie napisałem to używając,
node
a niecur
wprint
metodzie. Powiedz NIE przechwytywaniu „niejawniefinal
” miejscowych? )źródło
node
należy zadeklarowaćfinal
tutaj.cur
."Node" +
aby druga metoda była konieczna). / Nie mam imienia. Być może mógłbym stworzyć nazewnicze pytanie „ankietowe” (CW) i odrzucić je na zapomnienie.Tak, jeśli korzystasz z najnowszej wersji Java czyli wersji 8. Java8 umożliwia zdefiniowanie funkcji anonimowych, co było niemożliwe w poprzednich wersjach.
Weźmy przykład z dokumentacji java, aby dowiedzieć się, jak możemy deklarować anonimowe funkcje, klasy
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(); } }
Składnia klas anonimowych
Rozważmy instancję obiektu 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); } };
Anonimowe wyrażenie klasy składa się z następujących elementów:
new
operatoraNazwa interfejsu do zaimplementowania lub klasy do rozszerzenia. W tym przykładzie klasa anonimowa implementuje interfejs HelloWorld.
Nawiasy zawierające argumenty konstruktora, tak jak w przypadku zwykłego wyrażenia tworzenia instancji klasy. Uwaga: kiedy implementujesz interfejs, nie ma konstruktora, więc używasz pustej pary nawiasów, jak w tym przykładzie.
Treść, która jest treścią deklaracji klasy. Mówiąc dokładniej, w treści deklaracje metod są dozwolone, ale instrukcje nie.
źródło