Java8 - lambda, jak to dziala

0

Przegladam sobie nowosci w java 8 i zastganawiam sie...

//Old way:
button.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("The button was clicked using old fashion code!");
    }
});
 
//New way:
button.addActionListener( (e) -> {
        System.out.println("The button was clicked. From lambda expressions !");
});

jak dzialaja te lambdy ? Skad ten "drugi kod (new way)" wie, ze ma utworzyc obiekt ActionListener i przyslonic metode actionPerformed tak by zwracala tego string o_O ?

0

Drugi kod wie, że musi przesłonić metodę actionPerformed z tego prostego powodu, że interfejs ActionListener posiada tylko jedną metodę (jest to tzw. interfejs funkcjonalny). Wyrażenia lambda można używać tylko jeżeli w danym miejscu jest wymagany obiekt implementujący jednometodowy interfejs. Zauważ, że musisz użyć niejawnie typowanego argumentu (e) bo nie ma metody actionPerformed(), jest tylko actionPerformed(ActionEvent e).
Metoda którą przytoczyłeś nie zwraca String, tylko void.

0

Działa to w ten sam sposób jak klasy anonimowe, jednak java jest na tyle "mądra" że wie, interfejs ActionEvent jest funkcjonalny, czyli posiada tylko jedną metodę "abstract". Więc to ładnie wyglądające (e) -> {
System.out.println("The button was clicked. From lambda expressions !");
jest deklaracją metody actionPerformed .

Najlepszy materiał ktory to wytłumaczy: http://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html - nawet taki funkcjonalny cymbał jak ja to zrozumiał, więc problemów miec nie powinieneś.

1

Odpowiedź @niezdecydowany jest OK, a link od Oracle całkiem nieźle opisuje ogólne zasady działania. Rzecz jest jednak trochę bardziej skomplikowana.
Wyrażenia lambda w Javie 8 nie są w prosty sposób tłumaczone na klasy anonimowe. To nie tak działa. Zresztą można to zobaczyć po skompilowaniu kodu. Jak używasz klasy anonimowej w ramach klasy A proces kompilacji stworzy dwa pliki A.class i A$1.class. Gdy użyjesz lambd to drugi plik nie powstanie. Zatem lambdy nie są zastępnikami klas anonimowych.
Kompilator potrafi wywnioskować typy i odpowiednio dopasować to co ma podane w wyrażeniu lambda do tego co może przyjąć dana metoda. Co więcej generuje kod, który jest do pewnego stopnia dynamicznie typowany (nie jest to klasyczne dynamiczne typowanie jak np w JavaScript, ale na poziomie bytecodu wywołania zachowują się jak nietypowane). To dzięki wprowadzeniu w Javie 8 nowej instrukcji bytecodu w postaci słowa `invokedynamic, które delikatnie mówiąc olewa część sprawdzania typów :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1