Czy to w ogóle możliwe?
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ę :)
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
jej toString()
metodę.
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 zwyczaju java.util.Comparator<T>
do sortowania.
Oto przykład, jak możesz sortować pliki na String[]
podstawie 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]"
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).
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ć je Alpha
według określonego warunku. Aby to zrobić, możesz użyć pliku Predicate<Alpha>
. To jest funkcjonalny interfejs, który ma metodę, test
która akceptuje Alpha
i zwraca boolean
.
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
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 nie cur
w print
metodzie. Powiedz NIE przechwytywaniu „niejawnie final
” miejscowych? )
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
Poniższy przykład, HelloWorldAnonymousClasses, używa klas anonimowych w instrukcjach inicjalizacji zmiennych lokalnych frenchGreeting i spanishGreeting, ale używa klasy lokalnej do inicjalizacji zmiennej 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();
}
}
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.