Java 8'de çıkarım yazın


30

Java 8'deki yeni lambda gösteriminin tanıtılması (örneğin bu makaleye bakınız ) bir tür çıkarım gerektiriyor mu?

Öyleyse, yeni tür sistemi Java dilini bir bütün olarak nasıl etkiler?

Yanıtlar:


47

Cırcır ucube cevabında ve yorum başlığında oldukça fazla yanlış bilgi var . Yorum çok küçük olduğu için burada cevap olarak cevap vereceğim. Ayrıca, sonuçta bu bir cevap olduğundan, orijinal soruyu da cevaplamaya çalışacağım. (Ancak tip sistemler konusunda uzman olmadığımı unutmayın.)

İlk olarak, asıl soruya verilen kısa cevaplar Evet ve Hayır'dır. Evet, Java 8, Java 7'den oldukça daha fazla tür çıkarımına sahip olacaktır ve Hayır, Java 8'de "yeni" bir tür sistem yoktur, ancak bazı küçük değişiklikler olsa da .

Java 8 hala statik olarak yazılacak ve sınıflar ve arayüzler arasında hala ikilik olacak. İşlev türleri gibi yeni türler yoktur. Bir lambda tipi, esasen, tek bir soyut yöntemle sıradan bir arayüz olan "fonksiyonel bir arayüz" dür.

Arabirimler artık varsayılan yöntemler biçiminde koda sahip olabilir, ancak sınıfların tek miras ve çoklu arabirim mirası modeli aynı kalır. Elbette, varsayılan yöntemlerin varlığında yöntem çözümleme kuralları gibi bazı ayarlamalar vardır, ancak temelleri değişmez.

Tür çıkarımı ile çıkarılan herhangi bir tür açıkça yazılabilir. Kullanmak için mandal ucube 'in, örneğin,

Collections.<MyClass>sort(list, (a, b) -> { return a.order - b.order; });

temelde şeker

Collections.<MyClass>sort(list,
    (Comparator<MyClass>)((MyClass a, MyClass b) -> { return a.order - b.order; }));

Bu yüzden sparkleshy'nin "tip çıkarımı, tip sisteminin genişletilmesini gerektirmez" ifadesi temel olarak doğrudur.

Fakat sözdizimsel şekere geri dönmek için, bir lambda ifadesinin adsız bir iç sınıf için sözdizimsel bir şeker olmadığı ifadesini tekrar edeceğim . Cırcır kaçık bir lambda ifade Anonim iç sınıf örnekleme çevrilir ve Sparkleshy sadece bir lambda bu yeniden ileri sürülmektedir belirtti olan Anonim iç sınıf için sözdizimsel şeker, ama bu açıklamalar yanlıştır. Muhtemelen eski bilgilere dayanmaktadır. Erken lambda uygulamaları bu şekilde lambda uyguladı, ancak işler değişti.

Lambda ifadeleri iç sınıflardan anlamsal olarak farklıdır ve iç sınıflardan farklı şekilde uygulanırlar.

Lambda ifadeleri iç sınıflardan birkaç şekilde anlamsal olarak farklıdır. Bir lambda ifadesini değerlendirmek için her seferinde yeni bir örnek oluşturmak gerekmez. Ayrıca farklı yakalama anlambilimlerine sahiptirler, örneğin bunu farklı yakalarlar . Bir iç sınıfta, bu iç sınıf örneğidir, oysa bir lambda, bu etrafını saran örnektir. Aşağıdakileri göz önünde bulundur:

public class CaptureThis {
    void a(Runnable r) { r.run(); }

    void b() {
        a(new Runnable() { public void run() { System.out.println(this); }});
        a(() -> System.out.println(this));
    }

    public String toString() { return "outer"; }

    public static void main(String[] args) { new CaptureThis().b(); }
}

Yeni bir JDK 8 lambda yapısında ( b69 kullandım ) çıktı aşağıdaki gibi olacak:

CaptureThis$1@113de03
outer

Ayrıca, lambda ifadeleri iç sınıflardan tamamen farklı bir şekilde uygulanır. Demonte çıktısını karşılaştırırsanız, iç sınıf kodunun açıkça yaratma ile derlendiğini ve bir CaptureThis kurucusuna çağrıldığını görürsünüz, bu $ 1 iken, lambda ifadesi belirtilmemiş bir Runnable yoluyla bir Runnable yöntemini tedarik eden bir inokimyasal komuttan derlenir. Bunun nasıl çalıştığının ve nedeninin tam bir açıklaması için bkz. Brian Goetz 'JavaOne 2012 talk Lambda: Kaputun Altına Bir Göz .


2
". bunlar farklı Bu yakalama bir iç sınıfında, bu lambda ise, bu parça bir örneği, iç sınıf örneği olan aşağıdaki göz önünde bulundurun:" hala değiştirerek sözdizimsel şeker ile yapılabilir thisileMyClass.this
mandalının ucube

4
Birleştiricinin ötesine geçen (ve bazen bu bile) her şey tartışmalı bir şekilde sözdizimseldir. Ancak lambdalar iç sınıflar için sözdizimsel şeker değildir (artık). Benzer bir amaca hizmet ederler ve bazı benzerliklere sahiptirler, ancak kaputun altında (gözle görülür şekilde) farklılar.
Joachim Sauer

1
"Lambda ifadeleri iç sınıflardan anlamsal olarak farklıdır ve iç sınıflardan farklı olarak uygulanır.": Çok iyi açıklama için teşekkürler (+1). Bana göre hala net olmayan, neden lambdaların özel anonim sınıflar için sözdizimsel şeker olarak uygulanmadığı ya da başka bir deyişle, yeni anlambilimin getirdiği ekstra karmaşıklığın avantajı nedir? Bu, anonim iç sınıflarla çözülemeyen hangi sorunu çözüyor? (Ama yine de gönderdiğiniz bağlantıya bakmam gerekiyor, belki cevabı orada bulabilirim.)
Giorgio

1
@ Joachim Sauer: Sözdizimsel şekeri varolan bir anlambilim için yeni bir sözdizimi olarak görürüm. Yeni anlambilim ortaya çıktığında, sözdizimsel şeker hakkında konuşamayacağınızı düşünüyorum. Bu anlamda, assembler dışındaki her şeyin sözdizimsel şeker olduğunu iddia edemeyeceğinizi sanmıyorum.
Giorgio

3
@ Giorgio: Lambda'nın neden anonim iç sınıflar için sözdizimsel şeker olmadığı konusunda, bunun hakkında büyük bir tartışma olduğu ortaya çıktı. Brian Goetz'den gelen bu posta kararı özetliyor: mail.openjdk.java.net/pipermail/lambda-dev/2011-Ağustos/… . TL; DR kapıyı gelecekteki evrime açık bırakıyor ve bugün daha iyi performans elde ediyoruz. Goetz aslında ilgili bir soruyu cevaplıyor, Lambda nesnesi mi? Fakat cevabım Hayır veya Hatta Belki ise, bunun iç sınıflar için şeker olamayacağı anlamına gelir.
Stuart,
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.