Czytając specyfikację Java-8, widzę odniesienia do "typów SAM". Nie byłem w stanie znaleźć jasnego wyjaśnienia tego, co to jest.Co to jest "typ SAM" w Javie?
Co to jest typ SAM i jaki jest przykład scenariusza, w którym można go użyć?
Czytając specyfikację Java-8, widzę odniesienia do "typów SAM". Nie byłem w stanie znaleźć jasnego wyjaśnienia tego, co to jest.Co to jest "typ SAM" w Javie?
Co to jest typ SAM i jaki jest przykład scenariusza, w którym można go użyć?
Podsumowując the link Jon posted w przypadku kiedykolwiek idzie w dół, „SAM” jest skrótem od „jednej metody abstrakcyjnej” i „SAM-type” odnosi się do interfejsów jak Runnable
, Callable
itp lambda wyrażeń, nową funkcję w Java 8 , są uznawane za typ SAM i można je dowolnie konwertować.
Na przykład, z interfejsem takich jak to:
public interface Callable<T> {
public T call();
}
Można zadeklarować Callable
przy użyciu wyrażeń lambda tak:
Callable<String> strCallable =() -> "Hello world!";
System.out.println(strCallable.call()); // prints "Hello world!"
lambda wyrażenia w tym kontekście są przeważnie tylko cukier syntaktyczny. Wyglądają lepiej w kodzie niż w klasach anonimowych i są mniej restrykcyjne w zakresie nazewnictwa metod. Weźmy ten przykład z linku:
class Person {
private final String name;
private final int age;
public static int compareByAge(Person a, Person b) { ... }
public static int compareByName(Person a, Person b) { ... }
}
Person[] people = ...
Arrays.sort(people, Person::compareByAge);
Stwarza to Comparator
za pomocą określonej metody, które nie mają takie same nazwy jak Comparator.compare
, w ten sposób nie trzeba śledzić nazewnictwo interfejsu metod i można mają wiele nadpisań porównawczych w klasie, a następnie tworzą komparatory w locie za pomocą wyrażeń lambda.
zagłębiając ...
Na głębszym poziomie, Java implementuje je za pomocą instrukcji kodu bajtowego invokedynamic
dodanej w Javie 7. powiedziałem wcześniej, że deklarując lambda tworzy instancję Callable
lub Comparable
podobny do anonimowa klasa, ale to nie jest prawda. Zamiast tego, po raz pierwszy wywoływana jest nazwa invokedynamic
, tworzy ona procedurę obsługi funkcji Lambda przy użyciu LambdaMetafactory.metafactory
method, a następnie używa tej pamięci podręcznej w przyszłych wywołaniach Lambda. Więcej informacji można znaleźć w this answer.
To podejście jest złożone, a nawet zawiera kod, który odczytuje prymitywne wartości i odniesienia bezpośrednio z pamięci stosu, aby przekazać kod Lambda (np. Aby ominąć konieczność przydzielenia tablicy Object[]
w celu wywołania Lambda), ale pozwala na przyszłość iteracje implementacji Lambda w celu zastąpienia starych implementacji bez martwienia się o zgodność kodu bajtowego. Jeśli inżynierowie z Oracle zmienią podstawową implementację Lambda w nowszej wersji JVM, Lambdas skompilowany na starszej maszynie JVM skorzysta z nowszej implementacji.
Jako przykład, składnia linku jest nieaktualna. Spójrz na Lambda Expressions Java Trail, aby zobaczyć aktualną składnię.
jesteś pewny '# {" Witaj, świecie! " }; 'jest poprawna składnia? Myślałem, że wyrazi się to w wyrażeniu lambda, takim jak '() ->" Hello world! ". – asgs
Ah, tak. Właśnie przeczytałem komentarze @ Maurice'a. Powinieneś edytować ten post, aby odzwierciedlić najnowsze informacje. Dobrze wiedzieć, że '# {}' było jak Lambdas była wcześniej reprezentowana. – asgs
@asgs Miałem mały blurb na dole, wskazując na ścieżkę Java, ale poszedłem dalej i zaktualizowałem odpowiedź, tak czy inaczej, aby użyć obecnej składni. – Brian
Zobacz http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-3.html (które znalazłem po jednym wyszukiwaniu, który zabrał mnie do innego pytania SO). –
To dokładnie to, czego potrzebowałem. Dzięki! Z czystej ciekawości, jakiego słowa kluczowego użyłeś w wyszukiwaniu? – Cody
Nie kieruj ludzi do nieaktualnych informacji. Nieco dłuższe wyszukiwanie spowodowałoby przejście do bardziej aktualnej wersji: http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-4.html, która sama ma 18 miesięcy i teraz przestarzałe w wielu miejscach.Odpowiedzi na pytanie PO można znaleźć na stronie http://www.lambdafaq.org/what-is-a-functional-interface/, na jednej stronie w FAQ, na której staram się być na bieżąco, co do niedawna szybko się zmieniało rozwój języka i API. –