Java 8 yenilikler

Java 8 Yenilikler

java 8 yenilikler

Genc/Java8KodOrnekleri

22 Temmuz 2019 Tarihi itibariyle Java 8 ile gelen yenilikleri inceleyip bölüm bölüm anlatmaya karar verdim. Toplamda 4 bölümden oluşan bu seriye blog adresim üzerinden ulaşabilirsiniz. Konuları kod örnekleri ile birlikte açıkladım. Bu repoda tüm kod örneklerine toplu şekilde ulaşabilmek amacıyla oluşturuldu.

Eğer Java 8 ile gelen özellikleri detaylı bir şekilde incelemek isterseniz, bölüm bölüm ayrılmış şekilde yazılara aşağıdaki kısımdan ulaşabilirsiniz.

Java 8 Yenilikleri İle İlgili Makaleler

  1. Default Metodlar, Fonksiyonel Arayüz Kavramı, Lambda İfadeleri, Metod Referansı
  2. Yardımcı Fonksiyonel Arayüzler ( Consumer, Predicate, Supplier, Function )
  3. Stream API ve En Çok Kullanılan Metodları (forEach, filter, map, reduce, count gibi)
  4. Optional Sınıfı ve Date&Time API

Destek Çağrısı

Kod içerisinde ya da makaleler içerisinde hatalı bir yer görürseniz yeni bir issue açıp pull request gönderebilir veya mail yoluyla ulaşabilirsiniz. Bu sayade diğer arkadaşlarımızın yanlış öğrenmesini önleyebiliriz. Şimdiden teşekkür ederim.


Sevgiler

Tech Blogger

Uzun bir aranın ardından sonra herkese çok çok selamlar… Java 8 uzun zamandır (5 sene olmuş 😮 ) aramızda olan bir sürüm. Ancak getirdiği yenilikler oldukça kullanışlı. Bu özellikleri elimden geldiğince anlatmaya çalışacağım.
Java 12 çıktı yeni mi yazıyorsun diyenler için güncel olarak Java 8 kullanımı devam etmekte, geç olsun ama güç olmasın bilgi bilgidir mantığı ile yazıma başlıyorum.

Bu bölümde bahsedeceklerimi başlık altında toplamak gerekirse;


1. Default Metodlar

Java 8 öncesinde herhangi bir Interface ( Arayüz ) sınıfında gövdesiz metod yazmak mümkün değildi. Java 8 ile gelen default kelimesi ile artık Interface sınıflarda gövdeli metot yazmak mümkün. Şöyle ki;

Hesapla.java

Hesapla isimli Interface’imizi eğer implement/uygulamak istersek java bize 2 yol sunuyor. İlki Anonymous Inner Class olarak tanımlamak, ikincisi ise bu arayüzün implementasyonunu yapan bir sınıf oluşturmak.

  1. Anonymous Inner Class

2. Interface Implementation Class

Görüldüğü gibi 2 durumda da default anahtar kelimesi ile oluşturduğumuz metodun gövdesini yazmak zorunda kalmadık. Dilersek bu metodunda gövdesini oluşturabilirdik.


2. Fonksiyonel Arayüz ( Functional Interface )

Lambda ifadelerini uygulayabilmek için tasarlanmış ve sadece bir tane abstract ( soyut) metoda sahip fonksiyonel bir arayüzdür. Özellikleri ;


3. Lambda İfadeleri

Lambda ifadeleri, kısaca kendi başlarına tanımlanabilen herhangi bir classa ait olmadan iş yapabilen fonksiyonlardır. Buradaki fonksiyon kelimesi Java’cılara biraz garip gelebilir bildiğimiz metod diyebiliriz. İki adet parametre alan ve bu bu parametreleri çarpan bir fonksiyonu matematik ile şu şekilde ifade edebiliriz.

fonksiyon(x,y) -> x * y

Lambda bizlere daha okunabilir kod yazma imkanı ve yukarıda bahsetmiş olduğum Functional Interface’lerin implementasyonunu yapmamızda kolaylık sağlamakta.

Unutulmamalıdır ki, lambda ifadeleri yalnızca Functional Interface’lerle kullanılabilmekte.

Syntax olarak; (argument-list) -> {body} şeklindedir.

(argument-list) kısmında Interface sınıfında ki metodumuz tipine göre eğer parametre almayan bir metod ise boş bırakılır, parametre alan bir metod ise bu parametreler buraya yazılıp argüman olarak metoda gönderilir.

{body} kısmında ise metodumuzun ne iş yapacağı bilgisini tanımlayabiliriz. Yani kısaca metod gövdesi.

İlk olarak parametre almayan geri değer döndürmeyen soyut metod bulunduran yani Functional Interface’in lambda expression kullanarak implementasyonunu nasıl yapabiliriz ona bakalım.

Parametre alıp geri değer döndürmeyen bir metod için şu şekilde yapabiliriz;

Parametre alan ve geri değer döndüren bir fonksiyonumuz olduğunu düşünelim. Örneğin Integer tipinde iki sayı giriliyor ve bu girilen sayıları çarpıp geriye sonucu döndürüyor. ( fonksiyon(x,y) -> x * y )


Syntax konusunda kullanışlı bir kaç püf nokta… 💡


4. Metot Referansı

Java 8 öncesine kadar bir metoda parametre olarak ya primitive türde bir değişken ya da bir nesne gönderebiliyorduk. Artık bir metoda aynı formatta olan bir metodu referans alabileceğini söyleyebiliyoruz.

Tek soyut metoda sahip fonksiyonel arayüzlerle birlikte kullanılabilen “Metot referans” yöntemi bir lambda ifadesi gibi düşünülebilir.

Daha açık olmak gerekirse, bir lambda ifadesi tanımlanırken fonksiyonel arayüz sınıfımızda bulunan metodun tipini ve parametre alıp almamasını dikkate alıyorduk. Eğer bu yapıda olan herhangi bir metodumuz varsa bu metodu lambda ifadesi gibi kullanabiliyoruz.

Static olan ve olmayan metodlar için durum değişmekte. Syntax şu şekilde;
Static olan bir metod için referans verilirken ; ClassName::MetodIsmı
Static olmayan metod için ise ; ObjectReferans::MetodIsmı


Yazımı burada sonlandırıyorum. Bir sonraki bölümde java.util.function paketinin altında bulunan Yardımcı Fonksiyonel Arayüzler‘den bahsedeceğim. Elimden geldiğince anladığım kadarıyla bildiklerimi paylaşmaya çalıştım. Umarım işinize yarar. ⭐

Kaynaklar

  1. http://devnot.com/2017/java-8-hakkinda-bilmeniz-gerekenler/
  2. https://www.mobilhanem.com/java-8-lambda-ifadeleri/
  3. https://kodedu.com/java-8-ebook/
  4. http://www.javadunyasi.com/java-lambda-nedir-nasil-kullanilir/
  5. https://winterbe.com/posts/2014/03/16/java-8-tutorial/
  6. https://www.youtube.com/watch?v=oQCVaA11BLE
  7. https://kodedu.com/2014/03/java-8-lambda-expression-nedir-nasil-kullanirim/

Altı aylık geliştirmeden sonra, Oracle, yeni versiyonu Java SE15 açık kaynaklı bir OpenJDK projesi kullanan bir referans uygulaması olarak.

Java SE15 normal bir destek sürümü olarak sınıflandırılır, bir sonraki sürüme kadar yayınlanacak güncellemelerle. Java SE 11 uzun süreli destek ayağı olarak kullanılmalıdır (LTS) ve güncellemeler 2026'ya kadar yayınlanacak. Java 8 LTS, Aralık 2020'ye kadar desteklenecektir. Bir sonraki LTS sürümünün Eylül 2021'de yapılması planlanıyor.

Java SE 15'in başlıca yeni özellikleri

Bu yeni versiyonda, EdDSA RFC 8032 Signature için bir destek işlevi sunuldu, önerilen EdDSA uygulaması donanım platformlarına bağlı değildir, yan kanal saldırılarına karşı korumalıdır (tüm hesaplamaların sabit bir süresi garanti edilir) ve aynı koruma seviyesi ile performans açısından C ile yazılmış mevcut ECDSA uygulamasından daha iyi performans gösterir.

Başka bir değişiklik mühürlü sınıflar ve arayüzler için deneysel destek o diğer sınıflar ve arayüzler tarafından kullanılamazlar devralmak, genişletmek veya dağıtımı kaldırmak için.

Java SE 15'in bu yeni sürümünde ayrıca vurgulanan, doğrudan bayt kodu ile kullanılamayan gizli sınıflar için destek diğer sınıfların. Gizli sınıfların temel kullanımı, çalışma zamanında dinamik olarak sınıflar oluşturan ve bunları yansıtma yoluyla dolaylı olarak kullanan çerçeveler içindir.

Çöp toplayıcı ZGC (Z Çöp Toplayıcı) stabilize edildi ve genel kullanıma hazır olarak kabul edildi. ZGC, çöp toplamadan kaynaklanan gecikmeyi olabildiğince en aza indirmek için pasif modda çalışır (ZGC kullanılırken kesinti süresi 10 ms'yi geçmez) ve boyutları megabayttan çok terabayta kadar değişen küçük ve büyük yığınlarla çalışabilir.

Çöp toplayıcı Shenandoah stabilize oldu ve her yerde olduğu kabul edildi. Shenandoah, Red Hat tarafından geliştirilmiştir ve çöp toplama sırasında duraklama sürelerini azaltan bir algoritma kullanımı ile dikkat çekiyor Java uygulamalarına paralel olarak temizlik yaparken.

Buna ek olarak, aynı zamanda metin blokları desteği stabilize edildi ve dilde girildi: a değişmez dizelerin yeni biçimi Kaçış karakterlerini kullanmadan ve bloktaki orijinal metin biçimlendirmesini korumadan çok satırlı metin verilerini kaynak kodunuza eklemenize olanak tanırlar.

Öte yandan, Eski DatagramSocket API, şu şekilde yeniden çalışıldı: eski java.net.DatagramSocket ve java.net.MulticastSocket uygulamalarının yerini, hata ayıklaması ve bakımı daha kolay olan ve Loom projesi tarafından geliştirilen sanal iş parçacıklarıyla uyumlu modern bir uygulama almıştır.

Mevcut kodla olası bir uyumluluk ihlali durumunda, eski uygulama kaldırılmamıştır ve jdk.net.usePlainDatagramSocketImpl seçeneği kullanılarak etkinleştirilebilir.

Buna ek olarak, örüntü eşleştirmenin ikinci bir deneysel uygulaması önerilmiştir "instanceof" operatöründe, doğrulanmış değere erişmek için hemen bir yerel değişken tanımlamanıza olanak tanır.

Son olarak, equals (), hashCode () ve toString () gibi birkaç düşük seviyeli yöntemi açıkça tanımlama ihtiyacını ortadan kaldırarak, sınıf tanımları için kompakt bir form sağlayan, "kayıt" anahtar kelimesinin ikinci bir deneysel uygulaması da vurgulanmıştır. verilerin yalnızca alanlarda depolandığı durumlarda.

Nihayet öne çıkan diğer değişiklikler:

Si onun hakkında daha fazlasını bilmek istiyorsun bu yeni sürüm hakkında. Detayları kontrol edebilirsiniz Aşağıdaki bağlantıda.


Java8 ile Gelen Yeni Interface Özellikleri. Java’nın çoklu kalıtıma çözümü olan interface derleyici ile yapılan bir çeşit kontrat olarak nitelendirilir. Yani interface içerisinde belirtilmiş olan metotlar bu interface‘i gerçekleyen (implements) sınıflarda mutlaka bulunmalıdır. Interface’de belirtilen metotlar açıkça yazılmak zorunda olmasa da abstract metotlardır ve metot gövdeleri ilgili sınıflarda doldurulmalıdır. Aksi takdirde derleme işleminin yapılabilmesi için gerçekleyen sınıfın soyut olarak tanımlanması gerekir. Benzer şekilde interface içinde tanımlanan değişkenler de açıkça belirtilmese de final değişkenlerdir. Buraya kadar interface kavramını kısaca özetlemiş olduk.

Java8 ile interface yeni bir takım özellikler kazandı. Yukarıda kısaca bahsettiğimiz gibi interface içinde metot gövdesi olamıyordu. Java8 ile birlikte default anahtar kelimesi ile tanımladığımız metotların gövdesini interface içinde yazabiliyoruz. Bu şekilde metotlara varsayılan bir davranış belirleyip bu interface‘i gerçekleyen her sınıfta aynı metodu tekrar tekrar yazmaktan kurtulmuş oluyoruz. Bu metotların gövdesi interface içinde gerçeklenmiş olduğundan derleyici, metodu sınıf içinde ayrıca yazmamız için diretmiyor.

İkinci bir yenilik artık interface içinde static metot tanımlayabiliyoruz. Default metot gibi interface içinde gövdesi olan bu tip metotların doğal olarak static geçerlilik alanında çağırılabiliyorlar.

Aşağıdaki örnekle bu yenilikleri deneyimleyebiliriz. Örnekte NewJava8Interface isminde bir interface tanımlıyoruz ve içersinde birer adet default ve static metot tanımı yapıyoruz.

default void defaultMethod(){
System.out.println(“interface içinde tanımlanmış default metodu “);
}

static void staticMethod (){
System.out.println(“interface içinde tanımlanmış static metodu”);
}
}

Bu interface’i gerçekleyen somut sınıfımızı ise ConcreteClass ismiyle aşağıdaki gibi tanımlıyoruz. Main metodu içerisinde static geçerlilik alanında yani bir nesne yaratmadan interface ismi ile staticMehod() ‘u çağırıyoruz. Default metodu çağırabilmek için ise somut sınıfımızın (ConcreteClass) bir nesnesini yaratmak zorundayız.

public static void main(String[] args) {

// static context’de static metodu çağırıyoruz
NewJava8Interface.staticMethod();

// Bir nesne yaratıp default metodu çağırıyoruz
ConcreteClass object = new ConcreteClass();
object.defaultMethod();

}
}

Collection Framework yazı dizimizde bahsettiğimiz java.util.Colellection interface’i Java8 in bu yeni özelliklerini stream(),  parallelStream(),  forEach(),  removeIf(),  gibi default metotlar ile bolca kullanmaktadır.  Benzer şekilde Java.util.List interface’in de default sort metodu tanımlanmış olup artık sıralama yapmak için Collections yardımcı sınıfı olmadan sıralama yapabilmekteyiz. Yani Collections.sort(list) gibi bir kod yazmak yerine list.sort(Comparator obj); şeklinde sıralama yapabiliyoruz. (Comparator kullanımı önceki yazılarda mevcut)

Bu konuyla ilgili sorularınızı  alt kısımda bulunan yorumlar alanını kullanarak sorabilirsiniz.

Referanslar

www.mshowto.org

 

TAGs : java 8, java 8 interface, java 8 interface değişimleri, java 8 interface değisiklikleri, java 8 interface yenilikleri, java 8 interface ile gelenler, java 8 interface nedir, java 8 interface farklari

Bu İçeriğe Tepkin Ne Oldu?

java 8java 8 interfacejava 8 interface değisikliklerijava 8 interface değişimlerijava 8 interface farklarijava 8 interface ile gelenlerjava 8 interface nedirjava 8 interface yenilikleri

JAVA 9 ve Yenilikleri

JAVA 9 ve Yenilikleri

November 14, 2017

Uzun süredir beklenen Java 9 eylül ayı sonunda resmi olarak duyuruldu. Bu yazıda Java 9 ile gelen önemli yenilikleri ve geliştirmeleri örnekler de sunarak özetleyeceğim.

Çalışma Özeti:

  1. Java 9 REPL JSHELL (Java Shell)
  2. Java 9 Module System
  3. Process API Değişiklikleri
  4. Factory Metotlar: Immutable List, Set, Map
  5. Try with resource
  6. Reactive Stream
  7. Anounymous inner Class’lar için Diamond Operator
  8. Optional üzerinde yapılan geliştirmeler
  9. Stream Apı’ındaki geliştirmeler
  10. @Deprecated Anatosyonundaki Geliştirmeler
  11. Http 2.0 Client

İlk olarak, Java 9’u buradan indirebilirsiniz.

Bu yeni sürüm ile birlikte hangi yenilikler geldiği sorusunu, önemli olduğunu düşündüğüm yenilikleri içeren liste üzerinden yola çıkarak cevaplayalım.

Java REPL — JSHELL (Java Shell)

Java 9 ile birlikte yeni bir REPL (Read-Eval-Print-Loop) aracı olan Jshell resmi olarak yayınlandı.

Repl nedir?’ sorusuna yanıtlamak gerekirse; bir Shell arayüzüdür ve bu arayüz üzerinden girilen her kod, satırları okunarak çalıştırılır ve sonuçlar ekrana yazdırılır. Bir nevi komut satırı istemcisidir.

Java’nın REPL’i ise Jshell adıyla resmi olarak yayınlanmıştır. Böylece komut ekranı üzerinden kod parçaları yazılabilir ve direkt olarak yine burada çalıştırılabilir hale geldi. Artık özellikle küçük kod parçaları çalıştırmak istediğinizde dosyalar oluşturup derleyip çalıştırmaya ihtiyaç kalmadı.

Ek olarak noktalı virgülsüz de çalıştırabileceğiniz bir komut ekranı geldi. Burada istediğiniz kodları doğrudan çalıştırabilirsiniz. Oracle bu araç ile birlikte özellikle yeni başlayanlar ve pratik yapmak isteyenler için bire bir ortam sağlamış oldu.

Jshell’in kullanımını aşağıdaki örnekte bulabilirsiniz;

Örnekte görüldüğü gibi doğrudan kodlamaya başlayabilirsiniz. Java’da yapabileceğiniz her şeyi bu araç üzerinden de gerçekleştirebileceğinizi unutmayın.

Vereceğim örnekleri de sizlere jshell üzerinden sunacağım.

Yeni Modül Sistemi

Java 9’un yeniliklerinden biri de Modül sistemindeki değişimler. Bu değişimler JigsawProjesinin bir parçası olarak geliyor.

Java 9’dan önceki sürümlerde monolitik paketler (jarlar) ile Java tabanlı uygulamalar geliştiriyorduk. Yani bir Java projesi geliştirirken jar paketinin tamamını eklemek zorunluluğu projedeki dosya sayısını da artırıyordu.

Burada iki önemli sorun var. Bunlardan birisi kodu encapsulate etmek ve farklı modüller ile olan bağımlılıkları kontrol etmek. Diğeri ise dosya yollarını düzenlemenin zorluğu, tekrar eden dosyaların varlığına yol açmasıdır. Bunlara çözüm olarak Java 9 ile birlikte yeni bir Modül Sistemi geldi.

Artık her modül kendine ait bir tanımlayıcı içeriyor. “requires” kısmı bağlı olan modüler belirtilebiliyor. Buna ek olarak “exports” kısmında paketler arası erişilebilirlik yönetilebiliyor.

Aşağıda küçük bir örnek bulabilirsiniz;

module blog {

exports com.netas.blog;

requires modules;

}

Bu modüle descriptor sayesinde java modül yönetimi sağlayarak daha önce bahsettiğim iki sorunu da çözüyor.

Process API Değişiklikleri

Process Api, işletim sistemi içerisinde bazı proseslerin yönetimi için kullanılır ve Java Sanal Makinesini kullanarak bu işlevi yürütür. Bu API’yi kullanarak prosesi çalıştırabilir, duraklatabilir, kapatabilirsiniz.

Peki, bu Api’da ne gibi değişiklikler oldu?

Yeni sınıflar ile birlikte yeni metotlar eklenerek, işletim sistemleri üzerindeki işlemlerin yönetim ve kontrolünü kolaylaştırılmayı amaçlayan geliştirmeler yapıldı.

Yeni değişiklikler, Proccess sınıfında child veya daha alt prosesleri tanımlamanıza, bu proseslerin PID’sini (process id) öğrenmenize, bu prosesler hakkında bilgileri anlık olarak izleyebilmenize ve daha fazlasına daha esnek ve kolay bir şekilde olanak sağlamaktadır. Merak edenler için eklenen sınıflar şunlar:

java.lang.ProcessHandle

java.lang.ProcessHandle.Info

Küçük bir örnek ile gösterelim;

Örnekte ProcessHandle sınıfını kullanarak kullanılan prosesin bir objesini oluşturmuş olduk ve bu objenin bilgilerini info() metoduyla öğrendik.

Factory Methods for Immutable List, Set, Map and Map.Entry

Java 9 ile birlikte gelen yenilik değiştirilemez collection nesnelerini sadece tek kod satırı ile oluşturmamızı sağlıyor.

Önceden değiştirilemez collection oluşturmak için aşağıdaki gibi bir kod bloğu yazmamız gerekiyordu.

Set<Integer> set = new HashSet<>();

set.add(1);

set.add(2);

set.add(3);

set = Collections.unmodifiableSet(set);

Java 9 ile birlikte bunu kolayca tek satırda yapabiliyoruz.

Set<Integer> ints = Set.of(1, 2, 3);

List<String> strings = List.of(“netas”, “blog”);

Factory metotlarla immutable List, Set ve Map objelerini daha kolay yaratmaya olanak sağlandı. Bu yenilik metotların kullanırken boş ve boş olmayan objeler yaratmamızı sağlıyor.

Try with resource

Java 7 ile birlikte gelmiş olan exception handler yapısı kaynakları otomatik olarak yönetebiliyordu. Java 9’da bu konuda da bazı geliştirmeler yapıldı.

Örnek olarak aşağıdaki gibi bir okuma bloğumuz olduğunu varsayalım.

BufferedReader reader =newBufferedReader(newInputStreamReader(System.in));

Java 7 ve 8’de try bloğunu aşağıdaki şekilde tanımlayabiliyorduk;

try(BufferedReader r1 = reader){

}catch(IOException e)

{

}

Java 9 ile birlikte daha kısa ve okunaklı bir şekilde ifade edebiliriz;

try(reader){

}catch(IOException e){

}

Bu yenilik ile birlikte yazılan kod gereksiz parçalardan arınmış ve kod okunurluğu da artmış oluyor. Diğer bir artısı ise eskiden oluşabilecek kaynak sızıntılarından (resource leak) da kurtulmuş oluyoruz çünkü yeni bir obje tanımı yapmaya gerek duymuyoruz.

Reactive Streams

Reactive Streams asenkron stream işlemleri için non-blocking kullanılan bir yapıdır. Scala ve Akka’da oldukça popüler olan reactive programlama Oracle’ın kararıyla reactive stream api adı altında Java 9 ile birlikte Java’ya entegre edildi.

Publish/Subscribe Freamwork’üne implement edilen bu yapı asenkron olarak işlev görebilmektedir. Yeni arayüzler aşağıda belirtildiği şekildedir.

Anounymous inner Class’lar için Diamond Operator

Diamand Operator basitçe generic sınıflar için bir kurulum olarak tanımlanabilir. Java 9 ile birlikte artık inner sınıflar içinde kullanabilir hale geldik.

List<Map<Integer,Set<String>>> netasList = new ArrayList<Map<Integer,Set<String>>>();

Burada new ile tanımladığımız yapının içine hangi objeyi içereceğini tekrar vermemiz gerekmemektedir. Çünkü tanımlama aşamasında List içinde zaten tanımlamış oluyoruz.

List<Map<Integer,Set<String>>> netasList = new ArrayList<>();

Diamond operator’ü kısaca tanımladık. Konumuza dönecek olursak, Java 7 ile gelmiş olan diamond operatör yeniliğinde Java 8’de anounymous inner class’ların kullanımında kısıtlamalar göze çarpıyordu. Oracle da bunun farkına varmış olmalı ki, Java 9 ile bu sorunu ortadan kaldırdı.

Optional üzerinde yapılan geliştirmeler

Java 9 ile birlikte birkaç tane kullanışlı metot daha Optional Api üzerine eklenmiş oldu. En önemli etkilerinden birisi ise direkt olarak stream özelliğini optional ifadesiyle birlikte kullanabilir hale geldik. Yeniliklerden önemli olanları aşağıda kısaca açıkladım.

Stream: Java 8’de stream ederken optional ile değer kontrolü yapmamız gerekmekteydi. Şimdi ise otomatik olarak bu kontrolü yapar hale gelmiştir.

List<String> strings = streamOptional().filter(Optional::isPresent).map(Optional::get).collect(Collectors.toList());

List<String> newStrings = streamOptional().flatMap(Optional::stream).collect(Collectors.toList());

ifPresentOrElse: Bir değer var mı kontrolü yapar ve varsa değeri kullanarak istenilen işlemi gerçekleştirir. Aksi takdirde verdiğimiz diğer işlemi gerçekleştirmesini sağlayabiliriz.

Or: Bir değer varsa, o değer için Optional’ın değerini gönderecektir, diğer durumda or ile verdiğimiz işlemleri gerçekleştirebilir.

Stream API’ındaki geliştirmeler

Stream içim birkaç yeni ve kullanışlı metot eklenmiş oldu.

Özellikle buradaki iki metot çok önemli, bunlardan birisi takeWhile() ve bir diğeri ise dropWhile() metotlarıdır.

TakeWhile(): Kural yanlış olana kadar gelen değerleri stream eder.

DropWhile(): Kural yanlış olana kadar gelen değerleri düşürecektir.

Tek örnek üzerinde gösterelim, takeWhile ile değerlerde boş olan gelene kadar yazdıralım, yine aynı örnekte dropWhile ile boşluk gelene kadarki değerleri düşürelim ve sonrasını yazdıralım.

@Deprecated Anotasyonundaki Geliştirmeler

Java 8 ve öncesinde @Deprecated Anotasyonu sadece bir marker interface’inden ibaretti; Java 9 ile daha fazla bilgiye erişebilir hale geldi. Deprecated, açıklamaya ek olarak, gelecekte bir metodun var olup olmayacağını ve daha fazla kullanılmamasını gerektiğini anlatıyordu.

İki yeni parametre ile kullanışlılığı arttı: Bu parametrelerden birisi forRemoval ‘boolean’ değer alan ve bir metodun gelecek versiyonlarında var olup olmayacağını setlediğimiz özellik oldu; diğeri ise since parametresi hangi sürümden itibaren gerçekleşeceğini bildirmek için kullanılabilmektedir.

@Deprecated (forRemoval=true , since=”9")

HTTP 2.0 Client

HTTP 2.0 implementasyonu Java 9 ile birlikte Java’da var olmaya başladı ve HTTPURLConnection’ın yerini aldı. HTTP 2.0 ile Websocket de Java9 ile birlikte desteklenmeye başlandı. Bu yeni API’nin önemli noktalarından biri Java’daki ilk Incubator modül olmasıdır.

Incubator modül kavramı ise temelde Java’nın bir sonraki sürümlerinde de benimsenebileceğini ve üzerinde geliştirmelerin olabileceğini gösteriyor. Aksi durumda ise silinmesi söz konusu olabilir.

HTTP 2.0 ile birlikte iki yönlü iletişim, tek bir TCP bağlantısı ile çoğullama, uzun sürebilen bağlantılar, durum bilgisi içeren bağlantılar yapılabiliyor.


Benim önemli olarak gördüğüm yenilik ve geliştirmeleri açıkladım. Ama Java 9 çok çok daha fazlasını bize sunuyor. Burada özet olarak geçtiğimiz özellikleri bile uzun uzun incelemek gerekiyor.

Hoş geldin Java 9 :)

Subscribe to receive updates on new posts

Gökhan Ayrancıoğlu

Gökhan Ayrancıoğlu

Sr. Software Engineer @Heycar

Java 8 – Date API ile Gelen Yenilikler

Merhaba arkadaşlar,
mobilhanem.com üzerinden anlattığımız/yayınladığımız derslerimize Java 8 Yenilikleri başlığı altında üçüncü yazımız olan Date API ile Gelen Yenilikler ile devam ediyoruz. Akabinde devam edecek serinin içeriklerini buradan takip edebilirsiniz.

Java Date API nedir?

Java 8 ile birlikte gelen bu yenilik paketi altında yer alan Date ve Time sınıflarında bulunan eksiklikleri gidermek ve bazı sorunları ele almak için geliştirildi. Öncelikle var olan kısımda neler vardı ve Java 8 Date Api ile hayatımıza neler girdi, bakalım.

Öncelikle Java 8 öncesindeki ve sınıfları thread safe değildi. Peki thread safe ne demek? Kısaca bahsetmek gerekirse; Thread safe çoklu thread yapılarda karşımıza çıkan, birden çok thread’in bir kaynağa eriştiği durumlarda thread’lerin kilit (deadlock) oluşturmadan işlerini bitirmelerini sağlayan mekanizmadır. Bu genellikle bir kaynaktan veri okurken değilde kaynağa erişmeye çalışıldığı durumlarda, değerleri değiştirmek istediğimizde başımıza gelebilecek bir durumdur. Java’da immutable (değişmezlik) sınıflar thread safe’dir.

Konumuza dönecek olursak Java 8 ile birlikte gelen Date ve Time sınıfları immutable yani thread safe’dir. Böylelikle çoklu thread yapılarda bizleri thread senkronizasyonu probleminden korur. Java 8’den önce saat dilimini yönetmek için ekstra util class dediğimiz yardımcı sınıflar yazıyorduk java 8 ile birlikte Local ve ZonedDateTime bunları bizim için yapıyor.

Çoğunlukla en yaygın kullanulan sınıflar LocalDate, LocalTime ve LocalDateTime’dır. İsimlerinden de anlayacağınız üzere yerel zaman dilimleri hakkında bilgi vermektedir.

LocalDate ve LocalTime

Yeni Date Api’yi kullanırken karşılaşacağınız ilk sınıflar ve olacaktır. Başka bir sınıuf olan , bu iki sınıfın birleşimi olacak düşünülebilir. Bu sınıflar, tutarlı zaman dilimlerine sahip olan dağıtık sistemlerde zamanı temsil etmek için kullanılabilir.

Yeni Date Api ile gelen sınıflar Fluent Factory tasarım desenini kullanmaktadır. Buradaki Fluent Factory tasarım desenini kısaca bahsetmek gerekirse daha elverişli, okunaklı ve akıcı kod yazmamızı sağlayan bir yöntem. Bir sınıfın metodlarının sürekli sınıfında kendisini döndürdüğünü ve sürekli olarak o sınıfa bir anlam yüklediğinizi düşünün. Daha net olması açısından hemen bir örnek ile pekiştirelim.

LocalDate localDate1 = LocalDate.of(2018, 10, 15); LocalDate localDate2 = LocalDate.of(2018, Month.OCTOBER, 15); System.out.println(localDate1); System.out.println(localDate2);

Yukarıdaki örnekte LocalDate sınıfının of metodunu kullandık iki farklı kullanımı görmektesiniz. Her ikiside aynı çıktıyı vermektedir. of metodu geriye LocalDate döndürür ve dönen değer üzerinde başka LocalDate işlemleri yapmanıza olanak tanır.

LocalDate localDate1 = LocalDate.of(2018, 10, 15).plusDays(5);

Mesela dönen gün değerine 5 gün eklemek gibi düşünebilirsiniz. Sonuç olarak 2018, 10, 20 değerini göreceksiniz.

Yukarıda bahsettiğim Fluent Factory tasarım deseni bu minvalde geliştirilmiştir.

LocalDate sınıfına geri dönecek olursak bazı yardımcı metodlarını göstermek istiyorum.

LocalDateTime localDateTime = LocalDateTime.now(); // yyyy-MM-ddThh:mm:ss LocalDate theDate = localDateTime.toLocalDate(); int month = localDateTime.getMonth().getValue(); int day = localDateTime.getDayOfMonth(); int second = localDateTime.getSecond();

Yukarıda belirli bir tarihin ay, gün ve yıl cinsinden değerlerinin nasıl okunduğu gösterilmiştir.

Aynı şekilde LocalTime sınıfı da aşağıdaki gibi kullanılabilir.

LocalTime localTimeNow = LocalTime.now(); System.out.println(localTimeNow); LocalTime localTime = LocalTime.now(); System.out.println("Saat : " + localTime.getHour()); System.out.println("Dakika : " + localTime.getMinute()); System.out.println("Saniye : " + localTime.getSecond());

Yukarıda localTimeNow nesnesi uygulamanın o an çalıştığı sistem üzerindeki saati verir ve ardından da göreceğiniz üzere saat, dakika ve saniye’nin nasıl alındığını gördük.

Clock

Java 8 ile gelen Clock sınıfı bizlere sistemin bulunduğu bölgeye dayanarak bazı zaman bilgileri sunar.

Clock clock = Clock.systemDefaultZone(); ZoneId zone = clock.getZone(); System.out.println(zone.getId());;

Örneğin yukarıda uygulamanın çalıştığı sistemin hangi bölgede bulunduğunun bilgisini almış olduk. Bu kod parçasını çalıştırdığınızda çıktı olarak Europe/Istanbul verecektir. Çünkü kodu çalıştırdığım sistem Istanbul’da yer almaktadır.

Clock clock = Clock.systemDefaultZone(); System.out.println(clock.millis()); System.out.print(System.currentTimeMillis());

Yukarıda, bulunduğumuz bölge üzerinde anlık saati milisaniye cinsinden göstermiş olduk. Bu tür kullanımları anlık rastgele sayı üretmede kullanabilirsiniz. Her çalıştığı anda farklı sayı üreteceğinden milisaniye bazında aynı değer üretme ihtimali çok düşüktür. Çıktısı long değer olarak görebilirsiniz. Mesela; 1542837957763

Clock ile kullanılan bir başka metod offset^dir. Belirli bir an örnek alınarak o an ile herhangi saat değeri üzerine eklenerek istenilen tarihe gidilir. Mesela şu an dan 5 saat sonrasını istemek ya da “-” değer verdiğiniz 5 saat geriye gitmek gibi düşünebilirsiniz.

Clock clock = Clock.systemDefaultZone(); Clock clock1 = Clock.offset(clock, Duration.ofHours(5)); System.out.println(clock1.instant()); Clock clock2 = Clock.offset(clock, Duration.ZERO); System.out.println(clock2.instant()); Clock clock3 = Clock.offset(clock, Duration.ofHours(-10)); System.out.println(clock3.instant());

Yukarıda göreceğiniz üzere offset metodunun ikinci parametresi olan Duration sınıfının ofHours metoduna saat değeri parametre geçilerek istenilen tarihe gidilebilir. Örneğin ilk örnekte 5 saat sonrasını, ikinci örnekte herhangi bir değişiklik olmadan ve üçüncü örnekte ise 10 saat geri değer döndürür.

Bazen de saati sabit tutmamız gereken durumlar olabilir. Metodunuz zamana bağımlı bir şekilde çıktısı değişen bir metodunuz olduğunu düşünün ve bu metoda test yazarken zamanında sabit kalmasını ve o sabit kalan zamana göre testinizi yazmanız gerekebilir böyle durumlarda zamanı istenilen anda sabit tutabilirsiniz.

Instant instant = Instant.now(); ZoneId zoneId = ZoneId.systemDefault(); Clock clock = Clock.fixed(instant, zoneId); System.out.println(clock.toString());

Çıktı ekranında programın çalıştığı andaki saat dilimini göreceksiniz ve böylelikle saati sabit bir değerde tutmuş olursunuz.

Böylelikle Java 8 ile birlikte gelen Date Api hakkında temel bilgileri gösterdik, daha ayrıntılı bilgi edinmek için faydalandığım kaynaklara buradan ve buradan erişebilirsiniz.

Umarım faydalı olmuştur.

Bir sonraki yazımızda Java’da özel anotasyon yazımını öğreneceğiz, Bildiğiniz üzere anotasyonlar Java 5 versiyonundan itibaren var hem Java 8 öncesindeki kullanımından bahsedeceğiz hemde Java 8 ile birlikte gelen özelliklere değineceğiz.

Hoşçakalın.

14

Yusuf Çakal

Cumhuriyet Üniversitesi - Bilgisayar Mühendisliği (2014-2018)

1 JAVA 7 & JAVA 8 YENİLİKLERİ VE ÖZELLİKLERİ MELİH HİLMİ ULUDAĞ

2

3 Java SE 6 çıkış tarihi 11 Aralık Yaklaşık 4,5 yıl farkla Java SE 7 yayınlandı. Bu süreçte Java SE 6 nın 26 kadar güncellemesi verilse de, Java tutkunları JDK 7 için sabırsızlanıyorlardı.

4 JAVA 7 İLE GELEN YENİLİKLER Genel olarak, Performans güçlendirilmiş, kararlılık ve güvenirlilik sağlanmış. Daha zengin internet uygulamaları için Java Eklentisine yönelik iyileştirmeler yapılmış. Java kodu yazma ve optimize etme üzerine dile yenilikler ve iyileştirmeler getirilmiş. Java dışı dilleri daha etkin desteklemek için Java Virtual Machine iyileştirmeleri sağlanmıştır.

5 t1. t2 Problem JAVA 7 nin en iyi yanı,.. t4 t3 Problemi daha akıllı bir biçimde alt problemlere parçalayacak ve bu alt problemlerin çözümüne götüren iş parçaları arasında düşük eş zamanlama (synchronization) maliyeti olan yapılara ihtiyacımız var. Nihayet Java 7 Böl/Katıl çatısı (Fork/Join Framework) olarak adlandırılan bir çözüm sunarak çok çekirdekli sistemlerde uygulama geliştirmeyi nispeten kolaylaştırdı.

6 ÖNE ÇIKAN ÖZELLİKLER

7 İlkel tiplerden tam sayıların değerlerini tutabildiğimiz byte, short, int ve long tipleri artık binary şekilde tanımlayabiliyoruz. Yani sayıların başlarına 0b ya da 0B yazabiliyoruz. B nin burada küçük büyük harf olması herhangi bir şeyi değiştirmiyor.

8 Sayısal tipleri artık basamaklar arasına alt çizgi yazarak tanımlayabiliyoruz. Yalnız ondalıklı sayılarda noktadan hemen önce ya da sonra, long tiplerde de L harfinden önce alt çizgi kullanamıyoruz. Bunun yanında sayısal değerin en başına ya da en sonuna da alt çizgi koyamıyoruz. Alt çizgi kullanımı bize okunurluk sağlıyor.

9 Java nın sayılı eksikliklerinden görülen bu durum giderilmiş. Artık String değişkenleri switch komutu ile kıyaslayabiliyoruz. 6.0

10 Generic tipler kullanırken yazdığımız <> işaretleri arasındaki objeler, yaratılan instance larda da yine aynı şekilde yazılıyordu. Bu da sadece tanımda bile bir sürü karmaşaya yol açıyordu. Java 7 ile beraber new ile yarattığımız instance larda <> açıp kapatmak yeterli olacak.

11 Varargs kullanırken parametre sayısı belli olmayan değişkenleri metot içerisinde dizi gibi kullanabiliyorduk. Yalnız çalışma anında nesnelerin birbirlerine cast edilememesi (ClassCastException) gibi hatalarla karşılaşıyorduk. Artık derleyici gelişmiş uyarı ve hata mesajları veriyor.

12 Bilindiği üzere Try-Catch ile Hata java7 öncesi; try { } catch (NumberFormatException nfe) { } catch (XException xe) { }... java7'de ise; try { } catch (NumberFormatException nfe XException xe ) { } yakalamada birden fazla hatayı Catch de karşılamak için hep yeniden blok açılırdı. Artık «I» Operatörü ile birden fazla hata nesnesini tek seferde yazmak mümkün hale geldi.

13 DİĞER ÖZELLİKLER

14 Graphics2D java.lang.object java.awt.graphics java.awt.graphics2d Graphics java.lang.object java.awt.graphics Graphics Graphics2D Graphics2D iki boyutlu bir grafik, metin ve görüntüleme yetenekleri ile ilgili 2D Java API parçasıdır. Eski Graphics sınıfının aksine, Graphics2D koordinat dönüşümlerini destekler. Ayrıca geometri, renk ve metin mizanpajı üzerinde daha iyi kontrol sağlar.

15 vs Garbage Collector yapısı Garbage-First Collector yapısı Garbage-First Collector JDK7 nin 4.versiyonunda dahil olmuştur. GC1 in çoklu işlemcili bilgisayarlar (sunucu bilgisayar) için tasarlandığını söylemek gerekir. GC ye göre yetenekleri ve performansı arttırılmış yapıya sahiptir. Serial GC aynı anda tek thread(iplik) çalışabilir, aynı anda birden fazla thread çalışan GC sistemine ise Parallel GC adı verilmektedir. GC1 i GC den ayıran en belirleyici özellik Seri ve Paralel çalışma biçiminin daha başarılı olmasıdır.

16 JDK 7u4 ile birlikte G1 (Garbage First) olarak adlandırılan yeni bir çöp toplayıcısı geldi. Uzun dönemde, G1 in Java platformunun tek çöp toplayıcısı olması hedeflenmektedir. JSM nin en zayıf halkası çöp toplayıcıdır. Çöp toplama sırasında tüm uygulamanın iş parçalarının durdurulduğu, "tüm dünyanın durduğu" (stop-the-world) bir evre vardır. Bu evre boyunca uygulama hiçbir iş yapmaz. Ne yazık ki çöp toplayıcı algoritmaları Heap boyutuna göre ölçeklenebilir değildir. Heap boyutu arttıkça bu süre de hızla artmaktadır. Örneğin 64GB heap boyutu olan bir JSM de bu süre bir dakikayı aşabilir. G1 bu süre için bir sınır tanımlamamıza olanak sağlıyor.

17

18 Paket yapısında yenilik sağlanmış. Bu yapı jar yapısını daha düzgün hale getirdi. Versiyon desteğini, aktif erişimi(reflective), dağıtım formatını(java Module) bize sağlayacak. Dinamik yükleme modülü getirildi. Bu sayede Sistemin başlama süresi kısaltıldı.

19 Otamatik Get() ve Set() methodları oluşturulacak. Problemler çözüldü. İyileştirmeler yapıldı. Joda Time Library e geçildi. Not: Joda Time Library harici olarak indirilip sisteme ekleniyor. Joda Time Library: dayofyear, hourofday gibi basit sahalar ile önemli tarihsel bilgileri hızlıca elde etmemizi sağlarken sunduğu hizmet sınıfları ile karmaşık tarih işlemlerini kolayca yapabilmemize olanak verir. Yaygın olarak kullanılan kitaplık şu an için (sürüm 2.0) 8 takvim sistemini desteklemektedir.

20 Desktop uygulamaları için kullanılan swing kütüphanesi yenilenmiş. Swing kütüphanesi kullanarak daha görsel ve göze hoş gelen uygulamalar yazılabilecek. Bean binding özelliği iyileştirilmiş.

21 Hatırlatma: Java Uzantıları.xml ya da.properties olan bu dosyalarda tutulan veriler isim ve isme karşılık gelen değerler şeklinde tutulurlardı. Projelerimizde ayar yapacağımız zaman bu dosyaları gömerdik sisteme. Java 5.0 ile birlikte dile eklenen Annotation kavramı ile artık ayar dosyalarından kurtulduk. Not: Annotation değişkenleri olarak sadece primitive tipleri, String veenum tipleri ve tek boyutlu dizileri kullanabiliyoruz. Dizi elemanlarının tipleri de yine sadece ilkel tip, String ya da enum olabiliyor

22 Java 7 de ise, Annotation desteği genişliyor. Tür tanımlamada, ifadelerde ve diğer birçok elementde annotation daha çok kullanılacak. Derleyici ve statik analiz araçları için kodu çalışma zamanında doğrulayacak annotationlar yazmaya olanak vericek.

23 Sonuç olarak, JDK 7 ile sadece Java diline eklemeler yapılmamış. Java virtual machine(jvm) de bir oldukça iyileştirilmeler yapılmış. Örneğin hello world yazıp çalıştırdığımızda println çıktısını daha çabuk görebileceğiz. Çünkü Javanın çekirdeğindeki sınıf yükleme(class loader) kısmı oldukça iyileştirilmiş. Java dilinin yetenekleri arttırılmış ve JVM; pyhthon, matlab vs. gibi dinamik dilleri destekler hale geldi. JDK 7 de gelmesi planlanan bir çok özellik JDK 8 e aktarıldı.

24

25 JAVA 8 İLE GELEN YENİLİKLER Genel olarak, Lamda İfadeleri ve Sanal Genişletme Yöntemleri Java SE 8'in öne çıkan özelliği, Lamda ifadelerinin uygulanması ve Java programlama dili ve platformunu destekleyen yönleridir. Tarih ve Saat API'si Bu yeni API, geliştiricilerin tarih ve saati daha doğal, net ve anlaşılması kolay şekilde ele almasına izin vermektedir. Nashhorn JavaScript Motoru JavaScript motorunun hafif ve yüksek performanslı yeni bir uygulaması JDK'ya entegre edilmiştir ve mevcut API'ler yoluyla Java uygulamaları tarafından kullanılabilir. İyileştirilmiş Güvenlik Çağırana duyarlı yöntemlerinin mevcut elle yönetilen listesini, bu gibi yöntemleri doğru şekilde tanımlayan bir mekanizmayla değiştirir ve çağıranlarının hatasız şekilde keşfedilmesini sağlar.

26 Windows 8 i, Windows7 ve Vista dan ayıran küçük fark: Metro Kullanıcı Arabirimi. Yani, Microsoft, Başlat ekranındaki eklentileri desteklemediğinden, Java Başlat ekranında çalışmayacaktır. Java'yı çalıştırmak için Masaüstü ekranına geçmeniz gerekir.

27 Java 8 ile birlikte gelen Lambda ifadeleri ise fonksiyonel programlama yapmamıza olanak sağlıyor. Lambda ifadeleri sayesinde fonksiyonlar artık dilin birinci sınıf vatandaşı olarak işlem görecek. Fonksiyon tipinden bir değişken tanımlayabilecek ve fonksiyona parametre olarak başka bir fonksiyonu geçirebileceğiz.

28 Lambda Expressions Buradaki temel amaç, bir metoda bir obje yerine daha fazlasını vermek Şimdiye kadar J8 öncesinde, callback classları yazarak bu tip işlemleri yönetiyorduk. Bu da gereksiz yere uzun kodlar yazma gerekliliğini beraberinde getiriyordu. J8 deki Labmda sayesinde, 5,6 satırda yazdığımız kodları tek bir satırda yazabileceğiz. Bir örnek üzerinden açıklayım,

29 Üstelik Java 8 ile gelen yeniliklerin bir kısmından kodda basit değişiklikler yaparak yararlanmak mümkün olacaktır. Örneğin, Java 8'de Arrays yardımcı sınıfına, diziler üzerinde paralel sıralama yapmamızı sağlayan parallelsort() metodu eklenmiştir. Bu yeteneği kullanmak için tek yapmamız gereken,arrays.sort() çağrısını Arrays.parallelSort() çağrısı ile değiştirmektir. Paralel sıralamada Java 7 ile gelen Böl/Katıl çatısı kullanılmıştır. Java 8 ile birlikte sadece diziler üzerinde değil Collection API içinde yer alan kaplar üzerinde de paralel işler çalıştırmak mümkün olabilmektedir.

30

31 Java 7 ile birlikte çok uzun bir süre sonra Java Sanal Makinası (JSM) yeni bir bytecode ile tanıştı: invokedynamic. Her ne kadar yeni bir komutla tanışmış olsak da henüz Java 7'de derlendiğinde invokedynamic kodu ürettirecek herhangi bir Java ifadesi bulunmuyor. Java 8'de ise fonksiyonel programlama ve arayüz metot eklentileri (=Method Extensions) içeren kodlar derlendiklerinde invokedynamic kodu içerebilecek

32 invokedynamic ve JSM nin yapısındaki yenilikler Java programlama dili dışındaki dillerin, JSM üzerinde yüksek başarımla çalışmasına olanak sağlamaktadır. Java platformu çok dilli bir platforma doğru evriliyor. Bunun ilk uygulaması Java 8 ile birlikte gelen yeni Javascript motoru Nashorn olacaktır. Platformdaki bu yenilikler sayesinde Javascript kodlarının çok hızlı çalıştığına tanık olacaksınız. Java 7 bunun altyapısını oluşturdu. Java 8 ise ilk uygulamasını bize sunuyor.

33 Java 8 de çöp toplama ile ilgili dikkate değer tek gelişme Kalıcı Alan (=Perm(anent)Gen(eration)) olarak adlandırılan alanın genel Heap alanına eklemlenmesidir. Özellikle web uygulamalarında sık yapılan güncellemelerden kaynaklanan bu alanının dolmasına nedeni ile aldığımız taşma hatası ile şimdi daha seyrek karşılaşmak mümkün oldu.

34 Sonuç olarak, Java platformu aynı.net platformu gibi modüler değildir. Bir projede kullandığımız iki ayrı kütüphanenin, ortak bir kütüphanenin farklı sürümlerini kullanması durumunda, yürütme zamanında sınıf yükleyici ilk önce hangi sınıfı yüklemiş ise o sınıf kullanılacaktır. Sınıf yükleyici aynı sınıfın farklı sürümlerini yüklemesi ve yönetmesi mümkün değildir.bu problemi farklı yöntemlerle çözmek mümkün olsa da projeye geliştirme açısından zorluk katıyor.uzun süredir beklediğimiz modülerlik çözümü, Jigsaw projesi ile platforma kazandırılması amaçlansa da Java 8 e yetiştirilemeyeceği anlaşıldığı için çıkartılmıştı. Java 9 da bu problemin çözülmesini umuyoruz.

35 Beni dinlediğiniz için Teşekkür Ederim. Melih Hilmi ULUDAĞ Kaynaklar:

nest...

gelişim planı örnekleri 2022 doğum borçlanmasi ne kadar uzaktaki birini kendine aşık etme duası 2021 hac son dakika allahümme salli allahümme barik duası caycuma hava durumu elle kuyu açma burgusu dinimizde sünnet düğünü nasil olmali başak ikizler aşk uyumu yht öğrenci bilet fiyatları antalya inşaat mühendisliği puanları malta adası haritada nerede

© 2024 Toko Cleax. Seluruh hak cipta.