Сегодня я решил написать о самых главных нововведениях в Kotlin 1.4.0. Думаю, что начинающим Android разработчикам будет очень интересна данная тема и они смогут применить новые фишки в своих приложениях. Также, я надеюсь, что моя статья будет полезна и для профессиональных разработчиков, которые очень любят и помогают развивать Kotlin.
Основные темы, которые я затрону:
Нововведения в синтаксисе
Новые инструменты в IDE
Новый компилятор
Качество и производительность
Ну что ж, предлагаю вам налить себе кофе или чай, запастись сладеньким и можно начинать)
Немного о релизах Kotlin
На момент написания статьи самыми новыми релизами были:
Релиз | Дата и краткое описание | |
Kotlin 1.4.0 | 17 августа, 2020, основной пласт нововведений, который мы сегодня рассмотрим. Улучшение производительности, введение новых синтаксических конструкций и добавление новых функций в IDE. | |
Kotlin 1.4.10 Kotlin 1.4.20 Kotlin 1.4.21 | 7 сентября, 2020, исправление багов для Kotlin 1.4.0 23 ноября, 2020, несколько улучшений, такие как производительность и поддержка новых функций для JVM. 7 декабря, 2020, исправление ошибок для Kotlin 1.4.20 |
Нововведения в синтаксисе
SAM - интерфейсы
Одной из самых важных и довольно полезных фишек является добавление нового синтаксиса для SAM интерфейсов (SAM - Single Abstract Method, также интерфейс с одним методом называют функциональным).
Чтобы указать компилятору Kotlin о том, что перед нами SAM интерфейс нужно использовать ключевое слов fun
, как ниже в примере:
fun interface ItemSelectListener {
fun onItemSelect(position: Int): String
}
val items = listOf("Item 1", "Item 2", "Item 3")
val myListener = ItemSelectListener { position ->
items[position]
}
fun main() {
print("selected item -> ${myListener.onItemSelect(0)}")
}
Одно из применений: передача обработчиков событий в адаптер RecyclerView для отслеживания нажатия на элемент списка.
Данный подход сокращает количество строк кода и вводит дополнительные удобства.
Явный API режим
Kotlin предлагает новый явный API режим для разработчиков библиотек.
Основные моменты:
Явный API режим помогает делать API библиотек чистым и последовательным
Накладывает различные требования и ограничения на публичные API:
Строгое использование модификаторов доступа
Явное указание типов для свойств и функций, которые являются частью публичного API
Некоторые определения исключены из проверок: свойства data классов, первичные конструкторы и т.д.
Смешанные именованные и позиционные параметры
Довольно легко объяснить на примере. До Kotlin 1.4.0 нельзя было делать так:
fun foo(a: Int, b: String = "", c: Int) {}
fun main() {
foo(a = 10, "Hello, World", c = 100000)
}
В данном примере мы сначала указываем именованный параметр, а потом позиционный (строка "Hello, World"
). В ранних версиях Kotlin нужно было всегда указывать сначала позиционные.
Конечная запятая
Довольное удобно при обмене строк или копировании параметров функций
fun reformat(str: String,
wordSeparator: Char = ' ', // конечная запятая
) {
// TODO
}
Улучшения вызываемых ссылок на функции
Теперь вы можете использовать ссылки на функции, которые имеют default аргументы:
fun foo(a: Int = 0): String = "value -> $a" // параметр 'a' имеет значение по умолчанию 0
fun apply(f: () -> String): String = f()
fun main() {
println(apply(::foo))
}
Вы можете использовать ссылки на функции, которые возвращают любое тип там, где требуются функции возвращающие Unit
.
Например у нас есть функция foo
, которая принимает другую функцию, которая ничего не возращает (Unit
). Мы можем передать ей любую ссылку на функцию, у которой совпадает количество аргументов, а возвращаемый тип может быть любой:
fun foo(f: () -> Unit) { }
fun returnValue(): Int = 42
fun main() {
foo { returnValue() } // Так было до Kotlin 1.4.0
foo(::returnValue) // начиная с Kotlin 1.4.0 можно передать сюда функцию,
// которая возвращает любой тип
}
Вы можете адаптировать ссылки на функции, когда передается переменное количество аргументов:
fun foo(a: Int, vararg words: String) {}
fun useCase0(f: (Int) -> Unit) {}
fun useCase1(f: (Int, String) -> Unit) {}
fun useCase2(f: (Int, String, String) -> Unit) {}
fun test() {
useCase0(::foo)
useCase1(::foo)
useCase2(::foo)
}
В дополнение появилась поддержка передачи ссылки на функцию там, где используется ключевое слово suspend
fun lockUI() {}
fun takeSuspend(f: suspend () -> Unit) {}
fun test() {
takeSuspend { lockUI() } // до Kotlin 1.4.0
takeSuspend(::lockUI) // В Kotlin 1.4.0 можно сделать так
}
Использование break and continue внутри when выражений, включенных в цикл for
В Kotlin 1.4.0 вы можете использовать ключевые слова break
и continue
в операторе when
, когда он вложен в циклfor
(до этого нужно было создавать метки, более подробно)
fun foo(numbers: List<Int>) {
for (num in numbers) {
when {
num % 2 == 0 -> continue
num == 10 -> break
else -> println(x)
}
}
}
Новые инструменты в IDE
Новое гибкое окно создания проекта
Теперь вы можете создавать и конфигурировать различные типы проектов Kotlin более гибко и специфично:
Новое окно создания проекта позволяет:
Выбрать шаблон проекта (в будущем будет добавлено больше шаблонов)
Выбрать систему сборки (Gradle, Maven)
Посмотреть структуру проекта до его создания
Добавить/удалить модули, поддерживаемые данным шаблоном проекта
Настроить JVM версию, framework для тестирования и другие вещи.
Отладчик Корутин
Очень много разработчиков на Kotlin используют всеми известные корутины (а как же без них).
До Kotlin 1.4.0 приходилось полагаться на ведение логов и умственные усилия разработчика, чтобы отлаживать программы с наличием корутин.
Теперь появился новый инструмент, который находится в Debug Tool Window в Intellij IDEA, который позволяет:
Легко проверить состояние каждой корутины
Посмотреть значения локальных и захваченных переменных для корутин
Посмотреть полный стек создания корутины, а также стек внутри корутины (все фрэймы с локальными переменными)
Также можно получить полный отчет, воспользовавшись функцией Get Coroutines Dump
Новый компилятор
Главной целью создания нового компилятора было соответствие характеристикам:
Скорость
Создание общего интерфейса для разных платформ, которые поддерживает Kotlin
Обеспечение API для расширения компилятора
Основные улучшения по сравнению с предыдущим компилятором:
Новый более мощный алгоритм для автоматического вывода типов с поддержкой более сложных сценариев вывода типов и с улучшенниями для делегированных свойств. (данный алгоритм уже был доступен в версии Kotlin 1.3 при указании дополнительных опций, в новой версии он будет использоваться по умолчанию). Вы можете найти более десятка исправленных багов и ошибок в новом алгоритме на YouTrack
Унифицированный backend компилятора (в Kotlin есть несколько backend, таких как: Kotlin/JVM, Kotlin/JS и Kotlin/Native. Последний был основан на промежуточном представлении (IR) для Kotlin кода)
Сейчас компания JetBrains работает над более производительной frontend реализацией.
Frontend - это часть компилятора, которая разбирает код, разрешает имена, выполняет проверки типов и многое другое.
Качество и производительность
Одной из главных целей данного релиза является улучшение производительности и стабильности IDE, фокус на вещах, которые важны для разработчиков, а также сделать Kotlin более продуктивным и быстрым.
Основные улучшения:
Было исправлено более 60 ошибок производительности, включая большое количество случаев зависания IDE и утечек памяти
Прирост в скорости IDE, который можно увидеть, пройдя по ссылке (здесь время подсвечивания синтаксиса Kotlin при открытии большого проекта). Также на рисунке ниже показано время срабатывания автодополнения (которое уменьшилось по сравнению с предыдущими релизами)
И многие другие, которые напрямую связаны с созданием нового компилятора.
zx80
У меня никто из знакомых Андройд-разработчиков не переходил на Kotlin — все на Java, так зачем переходить на Kotlin если есть Java??
bugy
Он стильный, модный, молодёжный. Меньше кода, больше null-safety
Я бы спросил иначе: зачем использовать на андроиде Джаву, если есть Котлин
Если у вас уже есть огромный проект на Джаве, то его переводить на Котлин может и не обязательно. Но новые проекты, по-моему, явно стоит начинать писать на Котлине
VolCh
Например, Джаву знаешь, а Котлин нет, а у нового проекта жёсткий дедлайн. Рискнёте писать новый проект на незнакомом языке?
bugy
Конечно нет. Разумные действия должны быть в приоритете.
Есть ещё куча других причин использовать джаву вместо котлина.
Однако, на мой вкус, на андроиде котлин стоит использовать в бoльшем количестве случаев. Если это не вызывает критических проблем (совместимость, дедлайны, требования, кровь из глаз)
И котлин уже довольно давно на рынке. Потратить немного времени на изучение его основ, мне кажется, это лучше чем задавать вопросы в стиле "все на Java, так зачем переходить на Kotlin если есть Java??"
В конце конков каждый выбирает сам. Но выбор из-за незнания вряд ли является правильным.
VolCh
Обычно ровно наоборот: ратуют за переход на котлин не аргументируя особо зачем изучать, кроме спортивного интереса вдруг понравится. Метрик никаких нет, только куски кода на 5 строк в лучшем случае. Вот у вас есть что-то вроде: переписали проект на 100к loc — стало 50к, памяти стал меньше жрать, задачи которые раньше занимали неделю разработки только, сейчас через три дня в проде. Архитектуру и публичный АПИ пакетов при этом не меняли, просто переписали всё внутри их
Ну и для некоторых вопрос стоит не перейти с джава на котлин, а перейти с Х на джава или на котлин. А выглядит со стороны это как: джава — легаси, но переход возможен только на джава+котлин — своя экосистема у котлина гораздо менее развита.
bugy
К сожалению нет. Мы сейчас только потихоньку добавляем котлин в проект (по гитхабу, 7% репозитория). Новые тесты и простые утилиты на нем. Следующий шаг — новые продакшн модули делать на котлине.
Т.е. о трансформации имеющегося кода речи не идёт.
И объективных метрик у нас нет. У меня есть только субъективная: получение большего удовольствия от разработки.
Но в принципе, каждый может посчитать сколько джава кода является бесполезным бойлерплейтом в проекте:
(Map<String, List<MyCoolWrapper<Entity>>>)
Objects.equals
,object1.compareTo(object2) > 0
final
модификаторУ каждого свой подход к разработке, и какие-то пункты могут отсутствовать. Но в любом случае это всё визуальный мусор, который не влияет на функциональность (разве что в случае стримов) и ухудшает читаемость.
Но есть и куча подводных камней, типа совместимости с другими библиотеками (например ломбок вместе с котлин классами плохо работают), или медленная компиляция/автокомплит.
У меня бывший коллега в новой компании перевёл весь джава проект на чистый котлин (без джава кода, но в библиотеками), насколько я знаю. О каких-то критических проблемах он так и не сознался.
Кстати, на всякий случай уточню, я разделяю 3 "технологии" в данном случае:
На вопрос "бэкенд джава или котлин" я отказываюсь давать категоричные оценки. Размеры проектов и фреймворков слишком большие. Да и джава развивается
А вот c андроидом, на мой взгляд всё проще. Там и джава похуже, и проекты поменьше.
deinlandel
У меня «есть такое». Пишу бэкенд и Android-приложения, сейчас активно мигрирую на котлин (кстати, о плюсах — мигрировать на Котлин можно хоть по одному классу за раз, он абсолютно бесшовно совместим с Java-кодом в обе стороны включая различные библиотеки, работающие с reflection). По числу строк кода — в среднем на 50% меньше. Помимо в принципе менее «многословного» синтаксиса, при повседневном использовании, одна из самых удобных вещей — это очень обширная и продуманная стандартная библиотека с активным применением extension functions. Apache Commons и прочие Гуавы становятся практически не нужны.
Вот простенький примерчик. templates — это List объектов, которые надо отсортировать сперва по дате lastSubmit по убыванию, потом по label по возрастанию без учёта регистра. Теперь представьте, сколько всяких анонимных компараторов для этого надо нагородить в Java.
Плюс для Android-а корутины являются настоящим спасением, позволяя нормально работать в условиях необходимости постоянно прыгать между потоками и отменять выполняющиеся задачи в зависимости от жизненного цикла компонентов приложения.
«переход возможен только на джава+котлин — своя экосистема у котлина гораздо менее развита» — вот это непонятно абсолютно. Котлин работает на JVM и отдельная «экосистема» ему не требуется. И это плюс, а не минус — всё накопленное за годы развития JVM доступно без какой либо потребности в адаптации или портировании. Какие-то более удобные синтаксические штуки для крупных библиотек типа Spring уже написаны, но можно спокойно жить без них.
koperagen
Есть довольно много case study по разным направлениям разработки: бэкенд, mobile multiplatform. Про андроид от гугла, там как раз есть про LOC:
Впрочем согласен, что вместо этого в статьях чаще пишут про дата классы, в ответ на что довольно справедливо сказать «у нас есть lombok». Ну щто поделать (:
edogs
Оставляя в покое холиварные аргументы, хотя бы из-за этого developer.android.com/kotlin
p.s.: Лично мы в свое время свалили с java именно потому, что достали переусложненные конструкции, котлин лаконичнее и проще.
UnnamedUA
Зачем переходить на новые процы если есть пентиум 4?
Консервативные у вас друзья, придет время когда будут брать только на мобильное котлин/свифт/флаттер, а они все на java)
KiberneticWorm Автор
Kotlin имеет очень много преимуществ по сравнению с Java:
VIkrom
Пожалуй, нет языка программирования с экосистемой более развитой, чем у джавы.
Какие-либо пруфы по этому серьезному утверждению?
edogs
quakz
совместимость на словах только. Если про бэк говорить, что кучу раз сталкивался с тем, что не все инструменты работают нормально с котлином. Да, иногда это можно обойти костылями, но зачем?
Что же касается скорости разработки — я никакой разницы не заметил, кроме возможности костыли по-быстрому сделать, котлин в этом плане действительно удобней джавы. Только если вы нормально код пишите с использованием паттернов, весь этот синтаксический сахар не сильно помогать будет.
возможно действительно для мобильных приложений он будет лучше джавы, но на бэке — спасибо, не надо. Я писал на нем, когда он еще в бета версии был. Недавно снова пришлось вернуться и больше желания использовать его у меня нет. Бесполезная игрушка для тех, кому надоело на джаве код писать и хочется поиграться с чем-нибудь новым.
edogs
При этом много либ используется чисто котлиновских, т.к. на яве пришлось бы велосипедить, по сути котлиновские либы под андроид это целый набор фреймворков.
По скорости тоже разницы не заметили, но код читается намного проще, когда там меньше синтаксического мусора, пусть даже его количество убрано при помощи синтаксического сахара:)
quakz
на бэке инфраструктура огромная на джаве, поэтому обычно используют просто котлин без каких-либо котлиновских либ + фреймворки с либами на джаве. Первое, что в голову приходит — что кодогенерация не работает, если поддержки котлина нет (а ее нет обычно). Т.е. annotation processing сразу отваливается.
в идее, как ни странно, поддержка котлина заметно хуже чем у джавы. Лично у меня индексация котлиновского кода на больших файлах просто падала.
Плюс расширенные возможности языка провоцируют разработчиков писать костыли и велосипеды, а не использовать готовые инструменты и конфигурировать нормально тот же спринг. На джаве то же можно костыли городить, но там это немного сложнее будет.
Ну и про синтаксический сахар, который чтение упрощает: на мой взгляд упрощает чтение в первую очередь хорошая организация кода и использование паттернов. Если код написан хорошо — он будет читаемым и на котлине, и на джаве и на других языках. Если код лапша из костылей, то и сахар ему не поможет. Я видел и хорошие и плохие проекты на джаве и котлине. И лично я не вижу смысла ради практически такой же читаемости кода использовать котлин вместо джавы. Если бы еще котлиновские фичи использовались, корутины например, то был бы смысл, а так точно нет.
Есть, конечно, вариант использовать чисто котлиновские фреймворки для бэка, но они не особо популярны по моим наблюдениям. А непопулярные инструменты использовать на проекте, который потом неизвестно сколько поддерживать — такое себе решение. Если увольняться не собираетесь или совесть есть, то лучше что-то надежное использовать.
Хотя если мне очень сильно понадобится котлин использовать, то я и инструменты использовать буду, которые под него заточены. А если какой-нибудь спринг используешь, то проще и лучше джаву выбрать. Тем более при правильном использовании инструментов можно действительно скорость написания кода в разы улучшить
bugy
Подтверждаю
Не могу подтвердить. Я из тех "кому надоело джаву писать, вместо того чтобы фичи делать". Ну, всмысле, количество кода в джаве в разы больше. Взять те же .streams(), дата классы, перегрузку методов ради дефолтных параметров и т.п.
И самое полезное это null-safety, как по мне.
Но на вкус и цвет все фломастеры разные. Красные вкуснее
quakz
null-safety и элвис оператор действительно хороши, но ради них тянуть новый язык точно смысла нет
VIkrom
100% — это было скорее маркетинговым заявлением от JB.
KiberneticWorm Автор
Я поспешил с некоторыми выводами. И поэтому приношу изменения за допущенные ошибки.
Kotlin, по моему мнению, эффективен для мобильной разработки.
В каждой области должно быть свое наилучшее решение, потому что невозможно создать один инструмент, который будет использоваться для разработки любых программ (Web, Desktop, мобильные приложения и т.д.).
Bringoff
[sarcasm]Я подозреваю, на Kotlin перешли только Андроид-разработчики[/sarcasm]