Kotlin — statycznie typowany język programowania od JetBrains, działający na JVM i oficjalnie wspierany przez Google do tworzenia aplikacji na Androida od 2017 roku. Kotlin jest w pełni kompatybilny z Javą, ma zwięzłą składnię i wbudowane null-bezpieczeństwo. Kotlin Documentation — kompletny przewodnik po języku i standardowej bibliotece.
Najważniejsze
Kotlin — statycznie typowany język programowania stworzony przez firmę JetBrains (twórcę IntelliJ IDEA) i wydany w 2016 roku na licencji Apache 2.0. Kotlin kompiluje się do kodu bajtowego JVM, JavaScript i kodu natywnego (przez Kotlin/Native). Głównym obszarem zastosowania jest tworzenie aplikacji na Androida, aplikacji serwerowych i projektów wieloplatformowych.
Google ogłosiło Kotlin oficjalnym językiem tworzenia aplikacji na Androida na Google I/O 2017. Według danych Google (Android Developer Blog, 2026), ponad 85% nowych projektów w Google Play używa Kotlina. Język jest również aktywnie wykorzystywany w programowaniu serwerowym (Spring Boot, Ktor) i w projektach wieloplatformowych (Kotlin Multiplatform Mobile).
Kotlin jest w pełni kompatybilny z Javą — można wywoływać kod Javy z Kotlina i odwrotnie w ramach jednego projektu. Narzędzia do budowania (Gradle, Maven) obsługują oba języki, co umożliwia stopniową migrację z Javy na Kotlin bez przestojów w rozwoju.
Główne powody: zwięzłość — Kotlin wymaga średnio o 40% mniej linii kodu niż Java do rozwiązania tego samego zadania. Null- bezpieczeństwo — kompilator zabrania używania typów nullable bez sprawdzenia. Możliwości funkcyjne — funkcje wyższego rzędu, lambdy, extension functions i coroutines sprawiają, że kod jest bardziej wyrazisty i bezpieczniejszy.
Podstawowa składnia Kotlina łączy zwięzłość z jawnością. Zmienne deklaruje się przez val (immutable) i var (mutable). Kompilator używa type inference, ale jawne określenie typu jest obsługiwane. Funkcje deklaruje się słowem kluczowym fun.
package com.example.intro
// Stałe i zmienne
val appName: String = "KotlinApp" // niezmienna
var version = 1.0 // zmienna, typ wywnioskowany
// Funkcja z expression body
fun sum(a: Int, b: Int) = a + b
// String templates
fun greet(name: String) = "Witaj, $name! Wersja ${appName}_$version"
// Default and named arguments
fun createUser(
name: String,
age: Int = 18,
email: String? = null
)When-wyrażenie zastępuje switch w Javie i jest bardziej elastyczne: obsługuje sprawdzanie typów, zakresy, warunki i gałęzie bez break. Kompilator sprawdza wyczerpujący zakres dla enum i sealed-klas. Smart casts automatycznie rzutują typy po sprawdzeniu is, co eliminuje jawne rzutowania.
fun analyzeValue(value: Any) = when (value) {
is String -> "Łańcuch o długości ${value.length}" // smart cast
is Int -> "Liczba całkowita: $value"
in 1..10 -> "Liczba w zakresie 1-10"
else -> "Nieznany typ"
}Null- bezpieczeństwo — kluczowa cecha Kotlina, eliminująca NullPointerException na poziomie kompilacji. W Kotlinie typy domyślnie nie mogą być nullem. Aby zezwolić na null, dodaj ? do typu: String?. Kompilator wymaga jawnego sprawdzenia każdej nullable wartości.
// Typy nullable i non-null
val nonNull: String = "Zawsze nie null"
val nullable: String? = null // dozwolone
// Safe call — wykonuje się tylko jeśli nie jest nullem
val length: Int? = nullable?.length
// Elvis operator — wartość domyślna
val text: String = nullable ?: "Default text"
// Let — wykonanie bloku z non-null wartością
nullable?.let { value ->
println("Wartość: $value")
}Safe call operator (?.) zwraca null, jeśli obiekt przed operatorem jest nullem, i wywołuje metodę/właściwość w przeciwnym razie. Elvis operator (?:) dostarcza wartość domyślną, jeśli lewa strona jest nullem. Not-null assertion (!!) rzuca NullPointerException, jeśli wartość jest nullem — używaj tylko gdy jesteś w 100% pewien, że wartość istnieje.
Typy platformowe (platform types) — typy Javy z wywoływanego kodu Javy, których Kotlin nie może oznaczyć jako nullable lub non-null. Typ wyświetla się jako String! (z wykrzyknikiem). Deweloper sam odpowiada za null- bezpieczeństwo podczas pracy z kodem Javy.
Data-klasy w Kotlinie automatycznie generują equals(), hashCode(), toString(), copy() i componentN(). Eliminuje to boilerplate modeli Javy (POJO) i czyni kod czystszym. Deklaracja data class zajmuje jedną linię zamiast 20-30 w Javie.
data class User(
val id: Long,
val name: String,
val email: String,
val age: Int? = null
)
// Użycie
val user = User(1, "Anna", "anna@example.com")
val updatedUser = user.copy(age = 25)
// Destrukturyzacja
val (id, name) = user
println("Użytkownik #$id: $name")Destrukturyzacja pozwala rozłożyć data class na zmienne w jednej linii. Jest to wygodne przy pracy z parami, trójkami i innymi wartościami złożonymi. Destrukturyzacja jest obsługiwana dla data-klas, standardowych kolekcji (List, Map) i dowolnych klas z operator fun componentN().
Extension functions — mechanizm Kotlina do dodawania nowych metod do istniejących klas bez dziedziczenia. Rozszerzenia kompilują się do statycznych metod z parametrem receiver, więc dziedziczenie nie jest wymagane, a wirtualność nie jest obsługiwana.
// Extension function dla String
fun String.isEmail(): Boolean {
return this.contains("@") && this.contains(".")
}
// Extension property
val String.isPhoneNumber: Boolean
get() = this.matches(Regex("^\\+?[\\d-]{10,15}$"))
// Generic extension dla kolekcji
fun List<Int>.sumOfEvens(): Int {
return this.filter { it % 2 == 0 }.sum()
}
// Użycie
println("test@mail.com".isEmail()) // trueRozszerzenia są szeroko stosowane w Android SDK i bibliotekach. Na przykład Activity extensions w Android KTX to extension functions dla Activity, Fragment, View i innych klas. Rozszerzenia mogą być deklarowane jako funkcje top-level w pliku lub jako składowe klasy (member extensions).
Coroutines — to mechanizm programowania asynchronicznego w Kotlinie, pozwalający pisać nieblokujący kod w stylu sekwencyjnym. Coroutine wstrzymuje wykonanie na suspend-funkcji bez blokowania wątku i wznawia działanie po zakończeniu operacji. To alternatywa dla łańcuchów callbacków RxJava i AsyncTask.
import kotlinx.coroutines.*
// Suspend-funkcja — może się wstrzymywać
suspend fun fetchUserData(userId: Int): User {
// delay — suspend-funkcja, nie blokuje wątku
delay(500)
return User(userId, "User $userId", "user@example.com")
}
// Uruchomienie w coroutine
fun loadData() {
CoroutineScope(Dispatchers.Main).launch {
val user = fetchUserData(1) // wstrzymanie tutaj
updateUI(user) // kontynuacja na głównym wątku
}
}Dispatchers określają pulę wątków dla coroutine: Dispatchers.Main (wątek UI), Dispatchers.IO (operacje sieciowe/dyskowe), Dispatchers.Default (zadania CPU-intensywne). Structured concurrency gwarantuje, że coroutine nie pozostanie aktywna po zakończeniu scope — zapobiega to wyciekom pamięci.
// Równoległe uruchamianie przez async/await
suspend fun loadDashboard(): Dashboard = coroutineScope {
val user = async { fetchUserData(1) }
val orders = async { fetchOrders(1) }
val stats = async { fetchStats() }
Dashboard(user.await(), orders.await(), stats.await())
}Wybór między Kotlinem a Javą dla nowego projektu na Androida — fundamentalna decyzja architektoniczna. Kotlin oferuje bardziej nowoczesną składnię i wbudowane mechanizmy bezpieczeństwa, Java — szerszą pulę programistów i dojrzałe biblioteki.
| Cecha | Kotlin | Java |
|---|---|---|
| Null- bezpieczeństwo | Wbudowane (nullable/non-null) | Brak (adnotacje @Nullable) |
| Ilość kodu | −40% względem Javy | Boilerplate (getters/setters) |
| Data-klasy | data class (jedna linia) | POJO z Lombok lub ręcznie |
| Asynchroniczność | Coroutines (suspend/await) | CompletableFuture, RxJava |
| Extension functions | Wbudowane | Tylko przez klasy narzędziowe |
| Smart casts | Po sprawdzeniu is | Jawne rzutowanie (Type) obj |
| Kompatybilność wsteczna | 100% z Javą | — |
Wydajność Kotlina i Javy jest porównywalna — oba kompilują się do kodu bajtowego JVM. Kotlin czasami dodaje mikro-narzut na coroutines i inlining, ale jest to nieznaczne dla aplikacji mobilnych. Google i JetBrains aktywnie inwestują w Kotlina: Kotlin Multiplatform, Kotlin/Wasm i poprawę wydajności kompilatora K2.
Często zadawane pytania
Kotlin jest krótszy od Javy o 40% — mniej boilerplate'u. Kotlin dodaje null- bezpieczeństwo, data-klasy, extension functions, coroutines, smart casts, when-wyrażenia. Pełna kompatybilność z Javą: oba języki działają na JVM i mogą być używane w jednym projekcie bez konfliktów.
Typy domyślnie są non-null. Dla nullable używamy ?: String?. Kompilator zabrania bezpośredniego odwoływania się do nullable wartości. Safe call (?.) zwraca null przy null receiver. Elvis operator (?:) ustawia wartość domyślną. !! — wymuszone wyciągnięcie z możliwym wyjątkiem.
Coroutines — lekkie wątki, pozwalające pisać asyn chroniczny kod sekwencyjnie. suspend-funkcje wstrzymują się bez blokowania wątku. launch i async uruchamiają coroutines w CoroutineScope. Dispatchers.IO dla zapytań sieciowych, Dispatchers.Main dla aktualizacji UI.
data class automatycznie generuje equals(), hashCode(), toString(), copy() i componentN(). Przykład: data class User(val name: String, val age: Int). Destrukturyzacja przez val (name, age) = user. Odpowiednik record w Javie 14+, ale z dodatkową metodą copy().
Extension functions dodają metody do istniejących klas: fun String.isEmail(): Boolean. Kompilator zamienia je na statyczne wywołania z parametrem receiver. Dziedziczenie nie jest wymagane. Rozszerzenia są szeroko używane w Android KTX: view.showToast(), activity.viewModels().
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również