Java 8 – Method Reference
Java programlama dilinde metodlar, sınıfların içinde bulunan iş birimleridir.
Metodlara erişimin ise statik olup olmadığına göre iki erişim biçimi vardır. Statik metodlara sınıf üzerinden erişilebilirken, statik olmayan metodlara nesne üzerinden erişim sağlanabilmektedir.
Java 8 ile beraber metod birimleri, bir lambda ifadesine, dolayısıyla bir fonksiyonel arayüze karşılık olarak referans verilebilmektedir.
Lambda ifadeleri yazılırken, tek metoda sahip arayüzün (fonksiyonel arayüz) metod girdi ve çıktısı baz alınmaktadır. Eğer daha önce yazdığınız bir metodun girdi ve çıktısı, bir fonksiyonel arayüz metodunun girdi ve çıktısına birebir uyuyorsa, o metod bir lambda deyimi yerine kullanılabilmektedir.
Örneğin;
Consumer arayüzü T
türünde tek bir parametre alır. Metod dönüşü void
‘dir.
@FunctionalInterface
public interface Consumer<T> {
void accept(T t); // t-> {}
}
Yukarıdaki Consumer
arayüzü türünden bir nesneyi, e
→ {}
lambda deyimiyle oluşturabiliriz.
Consumer<String> consumerWithLambda = e-> {
};
Lambda ifadeleri yazarken metod girdi ve çıktısına odaklandığımıza göre, lambda deyimiyle birebir örtüşen metodları, lambda deyimleri yerine kullanabilir miyiz? Bunu aşağıdaki metod üzerinden düşünelim.
public void herhangiBirMetod(String e){
}
Yani herhangiBirMetod
metodunun imzasıyla Consumer<String>
arayüzünün accept metodunun imzası birbiriyle aynıdır. herhangiBirMetod
, String türünden tek bir parametre almaktadır, metod dönüşü ise void
‘dir. Bu uyum neticesinde eğer istenirse, bu metodun referansı ile Consumer<String>
türünden bir nesne oluşturulabilir.
Bir metodu referans vermek
Java programlama dilinde bir metodun nasıl referans verileceği metodun statik olup olmadığına göre değişmektedir. Bir metodun referans olarak verilebilmesi için ise ::
ikilisi kullanılır.
Statik metodlar sınıfa ait bileşenlerdir. Bu yüzden erişim kurulurken dahili olduğu sınıf üzerinden erişim kurulur.
Consumer<String> consumerWithMetRef = <ClassName>::herhangiBirMetod;
Statik olmayan metodlar nesneye ait bileşenlerdir. Bu sebeple nesnenin referansı üzerinden erişilmelidirler.
Consumer<String> consumerWithMetRef = <ObjectRef>::herhangiBirMetod;
Örnek 1
Şimdi birkaç örnek ile metod referansları deneyimleyelim. Aşağıda "Ali"
,"Veli"
,"Selami"
verilerini içeren bir List nesnesi bulunmaktadır. Bu nesnenin ise, forEach
isimli metodu bulunmaktadır. Bu nesnenin kabul ettiği parametre ise Consumer<String>
türündendir.
List<String> names= Arrays.asList("Ali,Veli,Selami");
names.forEach(new Consumer<String>() { (1)
@Override
public void accept(String s) {
System.out.println(s);
}
});
-
Sırayla konsole çıktılar.
Şimdi bu örneği Lambda
ifadesiyle yeniden aşağıdaki gibi yazabiliriz.
List<String> names= Arrays.asList("Ali,Veli,Selami");
names.forEach(s->{
System.out.println(s);
});
Lambda ifadesi, satır sayısı bazında kodu iyice kısalttı. Şimdi bu aynı işi metod referans kullanarak yapalım.
public class App{
static List<String> names= Arrays.asList("Ali,Veli,Selami");
// Statik metod
public static void herhangiBirMetod(String s){
System.out.println(s);
}
// Non-statik metod
public void digerBirMetod(String s){
System.out.println(s);
}
public static void main(String[] args){
names.forEach(App::herhangiBirMetod); (1)
// veya
App app=new App();
names.forEach(app::digerBirMetod); (2)
// veya
names.forEach(System.out::println); (3)
}
}
-
Statik metodu referans vermek
-
Non-statik metodu referans vermek
-
Diğer bir örnek
Örnek 2
Collections#sort
metodu ile bir dizi nesneyi sıralamak istiyoruz diyelim. Bu sıralamayı, metodun 2. parametresinde Comparator
türünden bir nesne ile kontrol edebiliriz.
List<Integer> numbers = Arrays.asList(5, 10, 1, 5, 6);
Collections.sort(numbers, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
});
- Not
-
Fonksiyonel olarak
Comparator
arayüzü vejava.util.BiFunction
arayüzü birebir aynıdır.
Şimdi anonim olarak oluşturulan Comparator
türünden nesneyi Lambda ifadeleriyle yeniden yazalım.
List<Integer> numbers = Arrays.asList(5, 10, 1, 5, 6);
Collections.sort(numbers, (o1, o2) -> o1 - o2)
Şimdi ise Lambda deyimi yerine metod referans kullanarak bu işi yapalım.
public Integer sirala(Integer o1, Integer o2){
return o1 - o2;
}
public void birMetod(){
List<Integer> numbers = Arrays.asList(5, 10, 1, 5, 6);
Collections.sort(numbers, this::sirala); (1)
}
-
Lambda yerine metod referansı
Metod referans kullanmak var olan iş mantığını kolay bir biçimde referans vermeye olanak sağlamaktadır.
Arşiv
Tekrar görüşmek dileğiyle.