Java 8: Bir makalede ana Lambda ifadeleri | CSDN blog seçimi

Yazar | Android Güçlü kardeş

Baş Editör | Guo Rui

Üretildi | CSDN Blogu

Bu makale, Lambda ifadelerinin ortak kullanımı ve yöntem referanslarının kullanımı dahil olmak üzere Java 8'deki yeni Lambda ifadelerini tanıtacak, Lambda ifadelerinin ilkelerini analiz edecek ve son olarak Lambda ifadelerinin avantajlarını ve dezavantajlarını özetleyecektir.

Genel Bakış

Java 8'de tanıtılan Lambda ifadelerinin ana işlevi, bazı anonim iç sınıfların yazılmasını basitleştirmektir.

Lambda ifadelerini kullanabilmenin önemli bir temeli, karşılık gelen işlevsel bir arayüzün olması gerektiğidir. Sözde işlevsel arayüz, içinde yalnızca bir soyut yöntem bulunan bir arayüzü ifade eder.

Lambda ifadelerinin diğer bir temeli, tür çıkarım mekanizmasıdır. Yeterli bağlamsal bilgi olması durumunda, derleyici, açık bir adlandırma gerekmeksizin parametre tablosunun türünü çıkarabilir.

Genel kullanım

2.1 Parametresiz işlev için kısa açıklama

Parametresiz bir fonksiyon, parametresiz bir fonksiyondur.Örneğin, Runnable arayüzünün çalıştırma yöntemi aşağıdaki gibi tanımlanır:

@FunctionalInterface

genel arayüz Runnable {

genel soyut boşluk koşusu;

}

Java 7 ve öncesinde genellikle şu şekilde kullanabiliriz:

yeni Konu (yeni Çalıştırılabilir {

@Override

public void run {

System.out.println ("Merhaba");

System.out.println ("Jimmy");

}

}).Başlat;

Java 8'den başlayarak, bağımsız değişken içermeyen anonim iç sınıflar aşağıdaki gibi kısaltılabilir:

- > {

İfadeyi yürüt

}

Bu şekilde, arayüz adı ve fonksiyon adı ihmal edilebilir. Sonra, Yukarıda Örnek şu şekilde kısaltılabilir:

yeni Konu(- > {

System.out.println ("Merhaba");

System.out.println ("Jimmy");

}).Başlat;

Sadece bir ifade olduğunda, kod bloğunu da kısaltabiliriz, format aşağıdaki gibidir:

- > ifade

Burada kullanılan ifadenin bir ifade olmadığını, yani sonuna noktalı virgül eklemeye gerek olmadığını unutmayın.

Sonra ne zaman Yukarıda Örnekte yalnızca bir ifade çalıştırıldığında, şu şekilde kısaltılabilir:

yeni Konu(- > System.out.println ("Merhaba")). Start;

2.2 Tek parametreli fonksiyon için kısa açıklama

Tek parametreli bir işlev, yalnızca bir parametreye sahip bir işlevi ifade eder. Örneğin, View içindeki OnClickListener arayüzünün onClick (View v) yöntemi aşağıdaki gibi tanımlanır:

genel arayüz OnClickListener {

/ **

* Bir görünüm tıklandığında çağrılır.

*

* @param v tıklanan görünüm.

* /

void onClick (Görünüm v);

}

Java 7 ve önceki sürümlerde, genellikle şunu kullanabiliriz:

view.setOnClickListener (yeni View.OnClickListener {

@Override

public void onClick (View v) {

v.setVisibility (View.GONE);

}

});

Java 8'den başlayarak, tek bağımsız değişkenli işlevlerin anonim iç sınıfları aşağıdaki gibi kısaltılabilir:

(değişken ismi) - > {

İfadeyi yürüt

}

Lambda ifadesi kendi kendine çıkarılabildiğinden sınıf adı ihmal edilebilir. Sonra Yukarıda Örnek, aşağıdaki iki şekilde kısaltılabilir:

view.setOnClickListener ((Görünüm v) - > {

v.setVisibility (View.GONE);

});

view.setOnClickListener ((v) - > {

v.setVisibility (View.GONE);

});

Tek parametreli fonksiyonlar parantezleri bile kaldırabilir, resmi de daha fazlasıdır Önermek Bu şekilde kullanın:

değişken ismi - > {

İfadeyi yürüt

}

Sonra, Yukarıda Örnek şu şekilde kısaltılabilir:

view.setOnClickListener (v- > {

v.setVisibility (View.GONE);

});

Yalnızca bir ifade olduğunda, kod bloğu yine de kısaltılabilir, biçim aşağıdaki gibidir:

(değişken ismi) - > ifade

Sınıf adı ve köşeli parantezler, aşağıdaki gibi yine de ihmal edilebilir:

değişken ismi - > ifade

Sonra, Yukarıda Örnek daha sonra şu şekilde kısaltılabilir:

view.setOnClickListener (v- > v.setVisibility (View.GONE));

2.3 Çok parametreli fonksiyonlar için kısayol

Çok parametreli işlevler, iki veya daha fazla parametreye sahip işlevlerle ilgilidir. Örneğin, Karşılaştırıcı arayüzünün karşılaştırma (T o1, T o2) yönteminin aşağıdaki gibi tanımlanan iki parametresi vardır:

@FunctionalInterface

genel arayüz Karşılaştırıcı < T > {

int karşılaştırma (T o1, T o2) ;

}

Java 7 ve öncesinde, bir koleksiyonu sıraladığımızda genellikle şunu yazabiliriz:

Liste < Tamsayı > list = Arrays.asList (1, 2, 3);

Collections.sort (liste, yeni Karşılaştırıcı < Tamsayı > {

@Override

public int karşılaştırma (Tamsayı o1, Tamsayı o2) {

dönüş o1 .com pareTo (o2);

}

});

Java 8'den başlayarak, çok parametreli işlevlerin anonim iç sınıfları aşağıdaki gibi kısaltılabilir:

(Değişken adı 1, değişken adı 2) - > {

İfadeyi yürüt

}

Aynı sınıf adı atlanabilir, ardından Yukarıda Örnek şu şekilde kısaltılabilir:

Collections.sort (liste, (Tamsayı o1, Tamsayı o2) - > {

dönüş o1 .com pareTo (o2);

});

Collections.sort (liste, (o1, o2) - > {

dönüş o1 .com pareTo (o2);

});

Yalnızca bir ifade olduğunda, kod bloğu yine de kısaltılabilir, biçim aşağıdaki gibidir:

(Değişken adı 1, değişken adı 2) - > ifade

Şu anda sınıf adı da çıkarılabilir, ancak parantezler ihmal edilemez. Bu ifade bir dönüş değeri gerektiriyorsa, bu durumda return anahtar sözcüğünün yazılmasına gerek yoktur.

bu nedenle Yukarıda Örnek daha sonra şu şekilde kısaltılabilir:

Collections.sort (liste, (o1, o2) - > o1 .com pareTo (o2));

Son olarak, bu örnek şu şekilde de kısaltılabilir:

Collections.sort (list, Integer :: CompareTo);

Huh, bu özellik nedir? Aşağıda bahsedeceğimiz şey bu: yöntem referansları.

Yöntem referansı

Yöntem referansları aynı zamanda geliştirmeyi basitleştirmek için kullanılabilen sözdizimsel şekerdir.

Lambda ifadelerini kullandığımızda, if "- > "Öğesinin sağ tarafında çalıştırılacak ifade, yalnızca bir sınıfın mevcut bir yöntemini çağırmak içindir, ardından Lambda ifadesini değiştirmek için" yöntem başvurusu "nu kullanabilirsiniz.

Yöntem referansları 4 kategoriye ayrılabilir:

  • Referans statik yöntem;

  • Nesneleri referans alma yöntemleri;

  • Sınıfları referans alma yöntemleri;

  • Referans yapım yöntemi.

Aşağıdakiler bu 4 kategoriye göre ayrı ayrı açıklanmıştır.

3.1 Statik yöntemlere başvurma

Yürütmek istediğimiz ifade, belirli bir sınıfın statik bir yöntemini çağırmak olduğunda ve bu statik yöntemin parametre listesi, arayüzdeki soyut işlevin parametre listesine karşılık geldiğinde, statik yönteme başvurma biçimini kullanabiliriz.

Lambda ifadesi aşağıdaki biçime uyuyorsa:

() - > Sınıf adı Statik yöntem adı ()

Bunu aşağıdaki formatta kısaltabiliriz:

Sınıf adı :: statik yöntem adı

Statik yöntem adından sonra parantez eklemeye gerek olmadığını ve hiçbir parametre olmadığını unutmayın, çünkü derleyici bunu çıkarabilir. Göstermek için aşağıda bölüm 2.3'teki örneği kullanmaya devam ediyoruz.

Önce bir takım sınıfı oluşturun, kod aşağıdaki gibidir:

public class Utils {

public static int karşılaştırma (Tamsayı o1, Tamsayı o2) {

dönüş o1 .com pareTo (o2);

}

}

Karşılaştırma fonksiyonunun parametreleri ile Karşılaştırılabilir arayüzün karşılaştırma fonksiyonunun parametreleri arasında bire bir karşılık geldiğine dikkat edin. O zaman genel Lambda ifadesi şu şekilde yazılabilir:

Collections.sort (liste, (o1, o2) - > Araçlar .com pare (o1, o2));

Yöntem referansı kullanırsanız, şu şekilde kısaltılabilir:

Collections.sort (list, Utils :: karşılaştır);

3.2 Nesnelere referans verme yöntemleri

Yürütmek istediğimiz ifade bir nesnenin bir yöntemini çağırmak olduğunda ve bu yöntemin parametre listesi arayüzdeki soyut işlevin parametre listesine karşılık geldiğinde, referans nesnenin yönteminin formatını kullanabiliriz.

Lambda ifadesi aşağıdaki biçime uyuyorsa:

() - > Nesne referansı. Yöntem adı ()

Bunu aşağıdaki formatta kısaltabiliriz:

Nesne referansı :: yöntem adı

Göstermek için aşağıda bölüm 2.3'teki örneği kullanmaya devam ediyoruz. Önce bir sınıf oluşturun, kod aşağıdaki gibidir:

public class MyClass {

public int karşılaştırma (Tamsayı o1, Tamsayı o2) {

dönüş o1 .com pareTo (o2);

}

}

Bu tipte bir nesne oluşturduğumuzda ve nesnenin yöntemini bir Lambda ifadesinde kullandığımızda, genellikle şunu yazabiliriz:

Sınıfım sınıfım = new Sınıfım;

Collections.sort (liste, (o1, o2) - > sınıfım .com pare (o1, o2));

Buradaki fonksiyonun parametrelerinin de bire bir karşılık geldiğine dikkat edin, bu durumda yöntem referans yöntemi aşağıdaki gibi kısaltılabilir:

Sınıfım sınıfım = new Sınıfım;

Collections.sort (list, myClass :: Compare);

Ayrıca çalıştırmak istediğimiz ifade, Lambda ifadesinin bulunduğu sınıfın bir metodunu çağırmak olduğunda, aşağıdaki formatı da kullanabiliriz:

this :: yöntem adı

Örneğin, Lambda ifadesinin bulunduğu sınıfa aşağıdaki yöntemi ekliyorum:

private int karşılaştırma (Tamsayı o1, Tamsayı o2) {

dönüş o1 .com pareTo (o2);

}

Lambda ifadeleri bu yöntemi kullandığında, genellikle şu şekilde yazılabilir:

Collections.sort (liste, (o1, o2) - > karşılaştır (o1, o2));

Yöntem referansını kullanırsanız, bunu şu şekilde kısaltabilirsiniz:

Collections.sort (list, this :: Compare);

3.3 Sınıfları referans alma yöntemleri

Referans sınıfın yönteminde kullanılan parametrelerin karşılık gelen biçimi, önceki ikisinden biraz farklıdır. Lambda ifadesi "- > "İsminin" sağ tarafında yürütülecek ifadeye - > Bu yöntem, "parametresinin solundaki birinci parametrenin bir örnek yöntemi ve ikinci parametre (veya parametrelerin olmaması), örnek yönteminin parametre listesine karşılık geldiğinde kullanılabilir.

Lambda ifademiz aşağıdaki biçime uyuyorsa, biraz kıvrımlı olabilir:

(Değişken 1) - > Değişken 1. Örnek yöntemi ()

O zaman kodumuz şu şekilde kısaltılabilir:

Değişken 1'e karşılık gelen sınıf adı :: örnek yöntem adı

Lambda ifadesini şu şekilde kullandığımızda yine de bölüm 2.3'teki örneği kullanın:

Collections.sort (liste, (o1, o2) - > o1 .com pareTo (o2));

göre Yukarıda Şu şekilde kısaltılabilir:

Collections.sort (list, Integer :: CompareTo);

3.4 Referans yapım yöntemi

Yürütmek istediğimiz ifade yeni bir nesne oluşturmak olduğunda ve nesnenin inşa yönteminin parametre listesi arayüzdeki fonksiyonun parametre listesine karşılık geldiğinde, "referans oluşturma yöntemi" formatını kullanabiliriz.

Lambda ifademiz aşağıdaki biçime uyuyorsa:

() - > yeni sınıf adı ()

Bunu aşağıdaki formatta kısaltabiliriz:

Sınıf adı :: yeni

Açıklamak için bir örnek verelim. Java 8, bir işlev arabirimi olan İşlev arabirimini tanıttı, kodun bir kısmı aşağıdaki gibidir:

@FunctionalInterface

genel arayüz İşlevi < T, R > {

/ **

* Bu işlevi şuna uygular: verilen argüman.

*

* @param t işlev bağımsız değişkeni

* @dönüş işlev sonucu

* /

R uygulama ly (Tt);

// Kodun bir kısmını atlayın

}

Bu arabirimi, belirli bir boyutta bir ArrayList oluşturmak için bir işlev uygulamak için kullanıyoruz. Genellikle bunu başarabiliriz:

Fonksiyon < Tamsayı, DiziListesi > işlev = yeni İşlev < Tamsayı, DiziListesi > {

@Override

public ArrayList uygulama ly (Tamsayı n) {

yeni ArrayList (n) döndür;

}

};

Liste listesi = işlev. uygulama ly (10);

Lambda ifadelerini kullanarak genellikle şu şekilde yazabiliriz:

Fonksiyon < Tamsayı, DiziListesi > function = n- > new ArrayList (n);

"Referans yapım yöntemini" kullanarak, bunu şu şekilde kısaltabiliriz:

Fonksiyon < Tamsayı, DiziListesi > function = ArrayList :: new;

Özel işlev arayüzü

İşlev arayüzünü özelleştirmek kolaydır, yalnızca tek bir soyut yöntemle, örnek kodla bir arayüz yazmanız yeterlidir:

@FunctionalInterface

genel arayüz MyInterface < T > {

geçersiz işlev (T t) ;

}

Yukarıda Koddaki @FunctionalInterface isteğe bağlıdır, ancak Artı Ek açıklama derleyici, arayüzün işlev arayüzü spesifikasyonuna uygun olup olmadığını kontrol etmenize yardımcı olacaktır. Tıpkı @Override notu eklemek gibi fonksiyonun geçersiz kılınmış olup olmadığını kontrol edecektir.

Uygulama prensibi

sonra Yukarıda Giriş bölümünde, Lambda ifadelerinin sadece anonim iç sınıfların yazımını basitleştirmek için olduğunu görüyoruz.Öyle görünüyor ki, tüm Lambda ifadelerini derleme aşamasında anonim iç sınıflarla değiştirmek yeterli görünüyor. Ancak gerçek durum böyle değildir JVM düzeyinde, Lambda ifadeleri ile anonim iç sınıflar arasında aslında bariz farklılıklar vardır.

5.1 Anonim iç sınıfların uygulanması

Anonim iç sınıf hala bir sınıftır, ancak sınıf adını açıkça belirtmemize gerek yoktur, derleyici otomatik olarak sınıfı adlandıracaktır. Örneğin, aşağıdaki kod:

public class LambdaTest {

public static void main (String args) {

yeni Konu (yeni Çalıştırılabilir {

@Override

public void run {

System.out.println ("Merhaba Dünya");

}

}).Başlat;

}

}

Derlemeden sonra iki sınıf dosyası oluşturulacaktır:

LambdaTest.class

LambdaTest $ 1. sınıf

LambdaTest.class'ın bayt kodunu daha ayrıntılı analiz etmek için javap -c LambdaTest.class kullanın ve bazı sonuçlar aşağıdaki gibidir:

public static void main (java.lang.String);

Kod:

0: yeni # 2 // sınıf java / dil / Konu

3: çift

4: yeni # 3 // sınıf com / örnek / benim uygulama lisans / lambda / LambdaTest $ 1

7: çift

8: invokespecial # 4 // Yöntem com / example / my uygulama lisans / lambda / LambdaTest $ 1. " < içinde > ": V

11: özel # 5'i çağırın // Yöntem java / lang / Thread. " < içinde > ": (Lav / dil / Runnable;) V

14: invokevirtual # 6 // Yöntem java / lang / Thread.start: V

17: dönüş

4: yeni # 3 satırının anonim iç sınıfın bir nesnesini oluşturduğunu görebilirsiniz.

5.2 Lambda İfadesinin Uygulanması

Sonra yapacağız Yukarıda Örnek kod, Lambda ifadeleri kullanılarak uygulanır; kod aşağıdaki gibidir:

public class LambdaTest {

public static void main (String args) {

yeni Konu(- > System.out.println ("Merhaba Dünya")). Start;

}

}

Bu noktada, derlemeden sonra yalnızca bir LambdaTest.class dosyası oluşturulacaktır. Bu dosyayı javap aracılığıyla yeniden derlemenin sonucuna bir göz atalım:

public static void main (java.lang.String);

Kod:

0: yeni # 2 // sınıf java / dil / Konu

3: çift

4: invokedynamic # 3, 0 // InvokeDynamic # 0: run: Ljava / lang / Runnable;

9: özel # 4'ü çağırın // Yöntem java / lang / Thread. " < içinde > ": (Lav / dil / Runnable;) V

12: invokevirtual # 5 // Yöntem java / lang / Thread.start: V

15: dönüş

Nereden Yukarıda Sonuç olarak, Lambda ifadesinin ana sınıfın özel bir yöntemi içinde kapsüllendiğini ve çağrılan dinamik talimat tarafından çağrıldığını bulduk.

Bu nedenle, Lambda ifadelerinin çağrılan dinamik talimat aracılığıyla uygulandığı ve Lambda ifadelerinin yazılmasının yeni sınıflar oluşturmayacağı sonucuna varabiliriz.

Lambda ifadesi anonim bir iç sınıf oluşturmadığından, this anahtar sözcüğü Lambda ifadesinde kullanıldığında, dış sınıfa bir başvuruya işaret eder.

Lehte ve aleyhte olanlar

avantaj:

  • Kod yazımını azaltabilir, anonim dahili sınıfların oluşturulmasını azaltabilir ve bellek kullanımından tasarruf edebilir.

  • Kullanılan arayüzleri ve soyut fonksiyonları hatırlamaya gerek yoktur.

Dezavantajları:

  • Okunaklılık zayıftır ve kodu okuyan kişilerin, Lambda ifadelerindeki ve soyut işlevlerdeki parametre türlerine aşina olması gerekir.

  • Hata ayıklama için uygun değildir.

Neden Çin'i seçtik
önceki
Büyük bir kör buluşma olarak, programcılar neden genellikle bekar?
Sonraki
Yeni bir programlama dili nasıl hızlı bir şekilde öğrenilir?
Huabei hesap kısıtlamasını iptal etti ve 3 bağımsız kota açabilir Netizen: Artık borçlanamaz
Neden programcılar her zaman böyle bir hayalet gibi giyinir?
Şangay ve Şenzen borsalarında yanıltıcı olmayan tek gösterge "devir hızı" Bu 8 özellik ortaya çıktığında, bu, ana gücün nihai birikimi tamamladığı ve hızla yükselişin yaklaştığı anlamına geliyor.
İnternet 50 yıl önce 3420 numaralı odada başladı
Buffy'nin özellikleri Çin borsasına nüfuz ediyor: Elinizde büyük paralar kazanmak istiyorsanız, "Zaman Çizelgesi'nin hacmi ve fiyatı ile aynı anda satın alın ve Zaman Çizelgesinin daha düşük hacminde
Çin-Yunanistan işbirliği ve değişim düzeyini kapsamlı bir şekilde iyileştirin ve BRICS'in verimli sonuçlarını teşvik edin
Orta Amerika Güzel Sanatlar Akademisi öğretmeni, antik şehir kapısından esinlenerek 5 yıl içinde Çinli bir A hayranı yaptı. Netizen: China Gundam
Çin Bilimler Akademisi'nin yabancı personeli internette uygunsuz yorumlar yaptı.
Python'un babası emekli olur, C dilinin babası vefat eder ve büyük programlama dillerinin kurucularının mevcut durumu ortaya çıkar.
PetroChina'da para kazanan bir hissedar, "Pozisyonunuzu artırmak için% 40 yükselirseniz,% 5 düşürürseniz piyasayı terk edersiniz" dedi. Hemen hemen tüm karlar yenilir ve tüm düşüşler önlenir.
Şampiyonlar Ligi: Sterling Bravo kırmızı, Manchester City deplasman 1-1 Atlanta skoru
To Top