Лучший способ понять язык — написать на нём код. Не читать про него, не смотреть вебинары, не сохранять статьи "прочту потом" (мы все знаем, чем это заканчивается). Kotlin с нуля: туториал для начинающих - 1Открыть IDE и написать что-то рабочее.

Этот туториал именно для этого. Мы пройдём от нуля до первого рабочего мини-приложения. Если знаете Java — будет ещё быстрее, буду показывать параллели.

Запустить Kotlin: два способа, один из них занимает ноль минут

Прямо в браузере. Заходите на play.kotlinlang.org — и пишете. Ничего не устанавливать, не настраивать, не читать Stack Overflow про то, почему не устанавливается. Идеально для первого знакомства.

В IntelliJ IDEA. Поддержка Kotlin встроена. Создаёте новый Kotlin-проект — и всё готово. Никаких плагинов, никаких плясок с бубном.

Первая программа:

fun main() {
    println("Hello, Kotlin!")
}

В Java это выглядело бы так:

public class Main {
    public static void main(String[] args) {
        System.out.println("Hello, Kotlin!");
    }
}

Оба варианта делают одно и то же. Просто в Kotlin нет public static void и класса-обёртки, потому что... а зачем они были нужны? Хороший вопрос. Java так и не ответила.

val и var: два слова, которые нужно запомнить

В Kotlin переменные объявляются через val или var.

val name = "Alice"   // Неизменяемая. Аналог final в Java.
var age = 25         // Изменяемая.

age = 26             // Ок.
name = "Bob"         // Ошибка компиляции.

Простое правило: используйте val везде, где значение не нужно менять. var — только когда реально нужно. Это как договориться с собой заранее: "я не буду это менять". И Kotlin проследит, чтобы вы не передумали в три часа ночи.

Тип можно не указывать — Kotlin выведет сам:

val score = 100     // Kotlin понимает: это Int
val name = "Alice"  // Это String

Или явно, если хочется:

val score: Int = 100
val name: String = "Alice"

Null-safety: как Kotlin убивает NullPointerException

Тони Хоар придумал null в 1965 году и позже назвал это своей "ошибкой на миллиард долларов". Звучит как самокритика, но на самом деле — скромность. NullPointerException обошёлся индустрии куда дороже.

В Java любая переменная может оказаться null. Компилятор молчит. Узнаёте об этом в runtime. В production. Ладно хоть не на демо у клиента — хотя и такое бывает.

Kotlin решил проблему на уровне системы типов:

var name: String = "Alice"
name = null  // Ошибка компиляции. Сразу. До запуска.

Если переменная может быть null — нужно сказать об этом явно через ?:

var name: String? = "Alice"
name = null  // Договорились, что nullable — теперь окей.

И что делать, когда нужно вызвать метод на такой переменной?

println(name?.length)        // Если null — вернёт null. Не упадёт.
println(name?.length ?: 0)   // Если null — вернёт 0. Оператор Elvis.

Оператор называется Elvis — потому что ?: похоже на причёску Элвиса Пресли. Это не шутка. Это официальное объяснение в документации.

Функции

В Java:

public static int add(int a, int b) {
    return a + b;
}

В Kotlin:

fun add(a: Int, b: Int): Int {
    return a + b
}

Или ещё короче — для функций из одного выражения:

fun add(a: Int, b: Int) = a + b

Kotlin умеет в параметры по умолчанию. В Java для этого нужно писать несколько перегруженных методов. В Kotlin — один:

fun greet(name: String, greeting: String = "Hello") {
    println("$greeting, $name!")
}

greet("Alice")        // Hello, Alice!
greet("Bob", "Hey")   // Hey, Bob!

Строковые шаблоны — $name в строке. Kotlin подставляет значение переменной прямо туда. Никаких + и конкатенаций — как в нормальных языках.

Data class: прощай, boilerplate

Вот задача. Нужна модель: пользователь с именем, возрастом и email.

В Java это конструктор, три геттера, три сеттера, equals(), hashCode(), toString(). Или Lombok. Или смириться и писать руками, как будто на дворе 2005 год.

В Kotlin:

data class User(val name: String, val age: Int, val email: String)

Одна строка. Компилятор генерирует всё остальное, включая copy():

val alice = User("Alice", 30, "alice@example.com")
val olderAlice = alice.copy(age = 31)

println(alice)
// User(name=Alice, age=30, email=alice@example.com)

Посмотрите на copy(). Вы создаёте новый объект, изменяя только нужные поля. В Java для этого обычно пишут Builder. Или просто страдают.

Extension functions: добавляем методы к чужим классам

Представьте: хотите добавить метод к классу String. В Java — утилитарный класс со статическими методами, и потом везде пишете StringUtils.doSomething(myString). Работает, но выглядит как костыль.

В Kotlin — extension function:

fun String.isValidEmail(): Boolean {
    return this.contains("@") && this.contains(".")
}

println("user@example.com".isValidEmail())  // true
println("это-не-email".isValidEmail())      // false

Выглядит как родной метод класса. Никакого наследования, никаких обёрток. Просто добавили метод — и пользуетесь.

Собираем всё вместе: валидатор пользователей

Возьмём всё, что узнали, и напишем что-то реальное.

data class User(val name: String, val email: String?)

fun String.isValidEmail() = contains("@") && contains(".")

fun validateUser(user: User): String {
    val emailStatus = user.email?.let {
        if (it.isValidEmail()) "валидный" else "невалидный"
    } ?: "не указан"

    return "${user.name}: email $emailStatus"
}

fun main() {
    val users = listOf(
        User("Alice", "alice@example.com"),
        User("Bob", "bob-not-email"),
        User("Charlie", null)
    )
    users.forEach { println(validateUser(it)) }
}

Вывод:

Alice: email валидный
Bob: email невалидный
Charlie: email не указан

Обратите внимание: null обработан без единого if. Оператор ?. и ?: делают это элегантно. Чарли не указал email — и никакого NPE. Жизнь прекрасна.

Это было только начало

Здесь разобрали основы: переменные, null-safety, функции, data class, extension functions.

Дальше интереснее. Корутины — асинхронный код без боли. Sealed classes — мощная альтернатива switch, которая не позволяет забыть обработать случай. Функциональная работа с коллекциями — map, filter, reduce в одну строку.

Если хочется изучить Kotlin системно, а не кусками из статей, которые потом теряются во вкладках — попробуй наш курс. 62 уровня, 1100+ задач с автопроверкой, 3 проекта в портфолио. Первый уровень бесплатно.

javarush.com/courses/kotlin

Читайте дальше по теме