🚀Kotlin'in Java'ya Göre Avantajları (Kotlin vs Java)

Kotlin’i Java’ya nazaran daha kullanışlı, avantajlı (ve havalı) kılan nedir, Kotlin'in avantajları nelerdir, neden Android için Kotlin kullanmalıyız? (kotlin vs java, java vs kotlin).

🏂 Kotlin Dünyasına Giriş

  • 👁️ Açık kaynaklıdır (Java 13 kapalı, openJDK hariç)

  • 🕰️ Java 8 eskidir, java 13 çıkmıştır

  • 🚀 Proje Kotlin dahi olsa Java sınıfları oluşturabilirsin

  • 💫 Java kodlarını Convert Java File to Kotlin komutu ile Kotlin kodlarına çevirebilirsin

  • 💁‍♂️ Tüm paketi çevirmek için paketi seç ve bu komutu kullan

  • 👀 Neden geçmen gerektiğini öğrenmek için yazıyı okumaya devam et

📢 Çok büyük projeleri parça parça geçirmeniz tavsiye edilir

✨ Değişken Tanımlaması

  • 💦 Java'daki final yapısı yerine daha sade bir arayüz sunar

  • 🚀 Değişken türlerinin tanımlanmasına gerek yoktur

  • 😱 Fonksiyon değişkenleri tanımlanabilir

  • ⚡ Statik değişkenler için scope sunar

  • 🕐 Daha sonra tanımlanacak değişkenler oluşturulabilir (lateinit)

🧐 Size birini mi anımsattı? (🐍 Python)

var metin = "yemreak" // String metin = "yemreak"
var metin: String = "yemreak" // String metin = "yemraek"
val metin = "değişmem" // final String metin = "değişmem"

/*
Foo
bar
*/
val uzunMetin = """
                Foo
                Bar
                """.trimIndent()

/*
if(a > 1) {
    return a
}
*/               
val uzunGirintiliMetin = """if(a > 1) {
                         |    return a
                         |}""".trimMargin()

var func: () -> Unit = {
    // Kardeş ben fonksiyonum
}

var func2: (Boolean) -> Unit = { bool ->
    // Kardeş ben parametreli fonksiyonum
}

var func2: (Boolean) -> Int = { bool ->
    // Kardeş ben bir integer döndürüyorum
    return 1
}

companion object {
    var metin = "yemreak" // static String metin = "yemreak"
    var metin: String = "yemreak" // static String metin = "yemraek"
    val metin = "değişmem" // static final String metin = "değişmem"
}

lateinit var sonrakiMetin
// ... 
sonrakiMetin = "yok"

// 0 sa true değilse false
val isEmpty: Boolean get() = size == 0

🐥 Nullable Objeler

  • ✨ Java'daki NullPointerException hatalarına odaklı bir çalışmadır

  • 🌌 Objeler null olabilir veya null olamaz şeklinde oluşturulur

  • 💁‍♂️ Default olarak null olamaz olarak atanır

var metin: String = "selam" // var metin = "selam" ile aynıdır
var metin: String? = null
metin?. // Varsa kullan
metin!! // Olduğundan kesinlikle eminim

var func: (() -> Unit)? = null
func?.invoke() // Null değilse çalıştır

// Dsoya varsa sayısı yoksa boş yaz
println(files?.size ?: "empty")

// Hata fırlatmalı atamalar
val email = values["email"] ?: throw IllegalStateException("Email is missing!")

🍎 Veri Sınıfları

  • 📈 Kotlin class veya data class yapısı ile get ve set kullanımı gerekmez

  • 🙄 Java ile resmin solundaki yapı gereklidir

🐣 Get Set Kullanımı

  • 🌌 Get set olmadan direkt olarak kullanabilirsiniz

  • ‍🧙‍♂ Kotlin, onu sizin için halletmekte

val arrayAdapter = ArrayAdapter<String>(
    wifiDirectActivity,
    R.layout.activity_wifi_direct,
    deviceNameList
)
wifiDirectActivity.lvPeer.adapter = arrayAdapter

👮‍♂️ Switch - Case

  • 🤝 Koşullu değer atama işlemlerini destekler

  • 📈 Sıradan switch yapısına göre daha verimlidir

val reasonMsg = when (reason) {
    WifiP2pManager.P2P_UNSUPPORTED -> "P2P desteklenmiyor"
    WifiP2pManager.ERROR -> "hata oluştur"
    WifiP2pManager.BUSY -> "cihaz başka bir bağlantı ile meşgul"
    else -> ""
}

💁‍♂️ Functional Arguments

  • 💦 Gereksiz yere parantez ( kullanımı yoktur

  • ⚙️ Bu yapı ile otomatik olarak son fonksiyona tanımlanan işlemler atanır

button.setOnClickListener { view ->
    // ...
}

/*
// Java kullanımı
button.setOnClickListener ( { view ->

});
*/

fun funcT(func1: () -> Unit, func2 () -> Unit) { }

funcT({ /* func1 */ }) {
    // func2
}

📢 Functional argument olursa, sadece metot {} kullanılması durumunda sadece son argümana değer atanır

➕ Function Extension

  • 💁‍♂️ Tanımlı olan sınıflara . operatörü ile metotlar ekleyebilirsiniz

  • 👇 Alttaki örnekte Uri sınıfına getInputStream metodu ekliyoruz

📢 Uri sınıfı temel java sınıflarından birisidir

🚀 Android Kotlin Extension'ları Android KTX paketi altındadır

🔪 Dizileri Parçalama

  • 🎯 Range metodu kullanılarak diziler parçalanabilmekte

  • 🐥 Çok kolay kullanımı vardır

🐍 Python dizi parçalama işlemlerine benzemektedir

val byteArray = ByteArray()
val slicedByteArray: List<Byte> = BUFFER.slice(3..5)

val bas = 10
val son = 100
val slicedByteArray2: List<Byte> = BUFFER.slice(bas..son)

💱 Dizileri Dönüştürme

  • 🚀 toTypedArrayeklentisi ile direkt olarak List'i argümana çevirebilirsiniz

📈 Java'dan çok daha verimli

val quakes: List<Quake> 
val args: Array<out Quake> = quakes.toTypedArray()

/* Java 
List<String> yourList = List.of("hello", "world");
yourVarargMethod(yourList.toArray(new String[0]));
*/

‍🧙‍♂ Detaylı bilgi için Fonksiyonlar alanına bakabilirsin.

💎 Keyword Argument

  • ✨ Değişkenlerin adları ile onlara değer atayabilirsin

  • ⭐ Python gibi dillerde olan bir kullanımdır

hasWifiDirectPermission(activity = activity)

fun hasWifiDirectPermission(activity: Activity): Boolean {
    return hasPermission(
        activity,
        Manifest.permission.ACCESS_FINE_LOCATION
    )
}

📢 Functional argument olursa, sadece metot {} kullanılması durumunda sadece son argümana değer atanır

💠 Parametre Olarak Fonksiyon

  • 💁‍♂️ Fonksiyonlar obje ise parametre olarak da kullanılabilir

  • 💡 Tanımlama şekli ile parametre olarak verilebilir

fun func(inFunc: (ByteArray) -> Unit) {
   // ...
   inFunc()
}

// Func kullanımı
func {
   // inFunc içeriği
]

var func2 = { byteArray -> /* ... */ }
func(func2) 

👨‍💼 Run - Apply - Let - Also

  • 👪 Bir değişkenin birden fazla metodunu kullanmayı sağar

  • 🐣 Apply objelerine değer atarsınız

  • ▶️ Run ile alt metotlarını kullanırsın, sonucunu döndürürsünüz

  • 🙋‍♂️ Let ile objeyi koşullu kullanabilirsin

  • 💁‍♂️ Also ile "işlemi bitirmeden bir de bunu yap" deriz

  • 📈 Tekrar tekrar yazmayı engeller

val wifiFilter = IntentFilter().apply {
    addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION)
    addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION)
}

obje.run {
    metot2() // obje.metot2()
    metot3() // obje.metot3() Döndürülür
}

obje?.let { // Koşullu kullanım
    it.metot2() // obje.metot2()
    it.metot3() // obje.metot3()
}

channel?.also { channel ->
    wifiReceiver = WifiDirectBroadcastReceiver(manager, channel, this)
}

// Yer değiştirme
a = b.also { b = a }

‍🧙‍♂ Detaylı bilgi için Scope Function ve Function Selections alanlarına bakabilirsin.

👀 Dokümantasyon Linkleri

  • 👇 Metotların üzerine geldiğinizde (hover) açıklamasında doküman linki olur

  • ⭐ Link üzerinden kullanım örneklerine erişirsiniz

📃 XML ID'lerini Koda Import Etme

  • 🔗 Kotlin otomatik olarak xml idlerini projeye dahil eder

  • 👨‍💻 import kotlinx.android.synthetic.main.<layour>.* ile dahil edilir

  • 💦 findViewByID metoduna gerek yoktur

👮‍♂️ İzinlerin Kontrolü

  • 📢 İzin tanımlanmadığında hata verir

  • 💁‍♂️ @SupressLint("MissingPermission") ile bunu engelleyebilirsiniz

  • 🤭 "Ne yaptığımın farkındayım, bana bulaşma" demek gibi

🚧 Coroutine

  • 🕊️ Thread işlemlerini kolaylaştıran bir hafif yapıdır

  • 👷‍♂️ Coroutine ile inline thread kullanabilirsin

  • 👮‍♂️ Main (UI), IO, Default thread yapıları ile arka plan işlemlerini yönetirsiniz

  • ✨ Otomatik olarak optimize edilirler

🧱 Dispatchers.Main🔣 Dispatchers.IO🎳 Dispatchers.Default

UI Thread işlemleri

Disk ve network işlemleri

CPU gerektiren işlemler

Fonksiyon çağırma

Database

Liste sıralama

View işlemleri

Dosya okuma & yazma

JSON parsing

LiveData işlemleri

Ağ işlemleri

DiffUtils

‍🧙‍♂ Detaylı bilgi için Coroutine alanına bakabilirsin.

🗃️ RoomDB Coroutine Scope

  • 👮‍♂️ suspend anahtar kelimesi ile thread gerektiren metotlar belirlenir

  • ❌ Thread gerektiren metotlar UI Thread üzerinde çalıştırılamaz

  • 🌌 Coroutine scope içerisinde kendilerine özgü thread ile çalıştırılır

  • 👋 AsyncTask'a elveda (zaten sevmedim 🙄)

ViewModel
fun refreshQuakes(quakes: List<Quake>) = viewModelScope.launch {
   repository.deleteAll() // Dao üzerinden suspend metottur
   repository.insert(quakes.toTypedArray())
}

/*
@Dao
abstract class QuakeDao {
	
	@Query("DELETE FROM ${Quake.TABLE_NAME}")
	abstract suspend fun deleteAll() // Burada suspend ile thread istiyoruz
	
}
*/

‍🧙‍♂ Detaylı bilgi için RoomDB - Android sayfasına bakabilirsin.

🔗 Faydalı Kaynaklar

🧐 Daha Fazla

Last updated

© 2024 ~ Yunus Emre Ak ~ yEmreAk