Оператор as в Kotlin используется для явного приведения типов (cast). Существует два варианта: as и as?. Один выбрасывает исключение, второй — безопаснее. Этот инструмент важен для работы с полиморфизмом, а также миграции данных и взаимодействии с внешними API.
В Java при приведении типов используется оператор-cast (TargetType)obj, который падает с ClassCastException при ошибке. Kotlin развил эту концепцию, добавив безопасный cast (as?), что позволило более удобно и эксплицитно управлять nullability и ошибками времени выполнения.
Жёсткое приведение типов в большом проекте опасно: если тип не совпадет, программа берёт и аварийно завершается (ClassCastException). Нужно минимизировать подобное поведение без Silent-error'ов или NPE. Важно качественно разделять ситуации, когда ошибка должна быть обработана, а когда корректно просто вернуть null.
Kotlin предоставляет два оператора:
as: жесткое приведение типа, при несовпадении типов выбрасывает ClassCastException.as?: безопасное приведение — возвращает null, если cast невозможен.val x: Any = "Hello, Kotlin!" val s1: String = x as String // Ok, x это String val s2: String? = x as? String // Ok, x это String val n: Int? = x as? Int // n = null, безопасный cast
as выбрасывает ClassCastException при ошибке.as? возвращает null, минимизируя аварийные ошибки.Всегда ли 'as' проверяет тип на runtime?
Да, если cast происходит с несовместимыми типами, возникнет ClassCastException. Однако для некоторых не-явных преобразований, например, между Int и Float, такого приведения не происходит — идиоматическое преобразование в Kotlin через методы (toInt, toFloat).
Можно ли использовать 'as' с nullable-типа в not-null-тип?
Да, но будьте осторожны: если значение окажется null, будет выброшено исключение. Любой cast nullable-типа к не-nullable без проверки может привести к ошибке в рантайме.
val x: String? = null val y: String = x as String // выбросит ClassCastException!
В чем разница между 'is' и 'as'?
'is' — это оператор проверки типа. Возвращает true/false, не приводит тип. 'as' именно приводит тип, и если невозможно, выбрасывает исключение (или возвращает null при использовании 'as?'). Часто их используют вместе для безопасного приведения:
if (x is String) { val s: String = x // smart cast }
as без проверки типа, что приводит к ClassCastException.В модуле парсинга данных все объекты парсятся через as, например, obj as Double. Если данные ошибочны — приложение падает с ClassCastException.
Плюсы:
Минусы:
Используется конструкция smart-cast (через is) или безопасный cast (as?):
val price = (obj as? Double) ?: 0.0
Плюсы:
Минусы: