Java-8 spesifikasyonunu okurken, 'SAM türlerine' referanslar görüyorum. Bunun ne olduğuna dair net bir açıklama bulamadım.
SAM türü nedir ve ne zaman kullanılabileceğine dair örnek bir senaryo nedir?
Java-8 spesifikasyonunu okurken, 'SAM türlerine' referanslar görüyorum. Bunun ne olduğuna dair net bir açıklama bulamadım.
SAM türü nedir ve ne zaman kullanılabileceğine dair örnek bir senaryo nedir?
Yanıtlar:
Özetlemek gerekirse Jon yayınlanmıştır linki 1 hiç iner durumunda, "SAM" "tek soyut yöntemi" anlamına gelir ve "SAM-tipi" gibi arayüzü belirtmektedir Runnable, Callablevardır, vs. Lambda ifadeleri, Java 8'de yeni bir özellik, SAM türü olarak kabul edilir ve bunlara serbestçe dönüştürülebilir.
Örneğin, bunun gibi bir arayüzle:
public interface Callable<T> {
public T call();
}
Aşağıdaki Callablegibi lambda ifadelerini kullanarak a bildirebilirsiniz :
Callable<String> strCallable = () -> "Hello world!";
System.out.println(strCallable.call()); // prints "Hello world!"
Bu bağlamdaki Lambda ifadeleri çoğunlukla sözdizimsel şekerdir. Kodda anonim sınıflardan daha iyi görünürler ve yöntem adlandırma konusunda daha az kısıtlayıcıdırlar. Bu örneği bağlantıdan alın:
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);
Bu Comparator, ile aynı adı paylaşmayan belirli bir yöntemi kullanarak bir yöntem oluşturur Comparator.compare, bu şekilde yöntemlerin arabirim adlandırmasını takip etmek zorunda kalmazsınız ve bir sınıfta birden fazla karşılaştırma geçersiz kılmaya sahip olabilirsiniz, ardından karşılaştırıcıları anında oluşturun. lambda ifadeleri.
Daha Derine İnmek ...
Daha derin bir düzeyde, Java bunları invokedynamicJava 7'de eklenen bayt kodu talimatını kullanarak uygular . Daha önce bir Lambda bildirmenin anonim bir sınıfın bir örneğini Callableveya Comparablebenzerini oluşturduğunu söylemiştim , ancak bu kesinlikle doğru değil . Bunun yerine, ilk invokedynamicçağrıldığında, LambdaMetafactory.metafactoryyöntemi kullanarak bir Lambda işlev işleyicisi oluşturur , daha sonra bu önbelleğe alınmış örneği Lambda'nın gelecekteki çağrılarında kullanır. Bu cevapta daha fazla bilgi bulunabilir .
Bu yaklaşım karmaşıktır ve hatta Lambda kodunuza geçmek için doğrudan yığın belleğinden ilkel değerleri ve referansları okuyabilen bir kod içerir (örneğin Object[], Lambda'nızı çağırmak için bir dizi ayırma ihtiyacını aşmak için), ancak Lambda uygulamasının gelecekteki yinelemelerine izin verir bayt kodu uyumluluğu konusunda endişelenmenize gerek kalmadan eski uygulamaları değiştirmek için. Oracle'daki mühendisler, JVM'nin daha yeni bir sürümünde temeldeki Lambda uygulamasını değiştirirse, eski bir JVM'de derlenen Lambda'lar, geliştiricinin kısmında herhangi bir değişiklik yapmadan yeni uygulamayı otomatik olarak kullanır.
1 Bağlantıdaki sözdizimi güncel değil. Geçerli sözdizimini görmek için Lambda İfadeleri Java Yolu'na bir göz atın .