Лучший способ понять язык — написать на нём код. Не читать про него, не смотреть вебинары, не сохранять статьи "прочту потом" (мы все знаем, чем это заканчивается).
Открыть 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 + bKotlin умеет в параметры по умолчанию. В 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 проекта в портфолио. Первый уровень бесплатно.
Читайте дальше по теме
- Что такое Kotlin и почему разработчики массово добавляют его в резюме — если хотите понять контекст: откуда взялся язык, почему Google на него поставил и что за история с Oracle.
- Java vs Kotlin: честное сравнение — теперь, когда вы видели оба синтаксиса, можно посмотреть на детальное сравнение: null-safety, data class, корутины, совместимость.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ