322 просмотра
От 9 февраля

Шпаргалка по вопросам с собеседования на Kotlin-разработчика

1. Преимущества Kotlin перед Java

Код на Kotlin компактнее на 30-40% Меньше кода = меньше ошибок, выше скорость разработки. Безопасная работа с обнуляемыми переменными (Null Safety) В отличие от Java, в Kotlin по умолчанию все типы являются non-nullable, то есть не могут принимать значение null. Присвоение или возврат null приведет к ошибке компиляции. Чтобы присвоить переменной значение null, в Kotlin необходимо явно пометить эту переменную как nullable (добавив после типа знак вопроса). В Java же при использовании ссылки на объект с указанным значением null, появляется исключение в виде «NullPointerExpertion!». Функции-расширения (Extensions) Kotlin позволяет расширять класс путём добавления нового функционала без необходимости наследования от такого класса. Это реализовано с помощью специальных выражений, называемых расширения. Например, вы можете написать новые функции для класса из сторонней библиотеки, которую вы не можете изменить. Такие функции можно вызывать обычным способом, как если бы они были методами исходного класса. Этот механизм называется функцией расширения. Классы данных (data classes) Разработчику на Java приходится писать много стандартного, но часто встречающегося кода (т.н. шаблонный код или boilerplate). В Kotlin же есть возможность создания специальных классов для определения полей для хранения данных, конструктора, функций сеттеров и геттеров для каждого поля, и функций Hashcode(), toString() и equals(). Для этого достаточно добавить data в определение класса, затем компилятор сделает все сам. Синглтоны на уровне языка (Object) В Java все должно объявляться внутри класса. Но в Kotlin все иначе. Компоненты могут объявляться за пределами класса, и это автоматически делает их статическими. Поэтому нам не требуется ключевое слово static. В Java статические члены обрабатываются не так, как члены-объекты. Это означает, что для статических членов нам недоступны такие вещи, как реализация интерфейса, помещение экземпляра в ассоциативный список (map) или передача его в качестве параметра методу, который принимает объект. В Kotlin static не является ключевым словом и вместо статических членов используются объекты-компаньоны, позволяющие преодолеть вышеуказанные ограничения. В этом и заключается преимущество. Даже если члены объектов-компаньонов выглядят как статические члены в других языках, во время выполнения они все равно остаются членами экземпляров реальных объектов и могут, например, реализовывать интерфейсы. Корутины Kotlin предоставляет возможность создавать дополнительные потоки, однако в нем также существуют т.н. корутины (сопрограммы), которые позволяют использовать меньше памяти в сравнении с обычным потоком, т.к. реализованы они без стека. Корутины же в свою очередь способны выполнять интенсивные и длительные задачи методом приостановления выполнения без блокировки потока и его последующего восстановления. Что в дальнейшем позволяет сгенерировать асинхронный код без блокирования, который при его выполнении не отличить от синхронного. К тому же, они генерируют эффектные доп. стили например async или await.

2. Подход к исключениям (exception) в Java и Kotlin

Одним из ключевых отличий между Java и Kotlin является подход к исключениям. В Java есть два типа исключений: checked и unchecked. Checked исключения это те, которые должны быть обработаны в коде, иначе компилятор не позволит коду скомпилироваться. Unchecked исключения не требуют обработки в коде. С точки зрения исключений компилятор Kotlin отличается тем, что не различает checked и unchecked исключения. Все исключения — только unchecked, поэтому нет необходимости отлавливать или объявлять какие-либо исключения (вы самостоятельно принимаете решение, стоит ли их отлавливать и обрабатывать). Такой подход был выбран разработчиками Kotlin, чтобы упростить и ускорить процесс разработки, сократив количество бойлерплейта и улучшив читаемость кода. Однако, это может привести к тому, что некоторые ошибки могут быть упущены при компиляции и проявиться только во время выполнения программы. Некоторые разработчики считают, что отказ от checked исключений является недостатком Kotlin, поскольку это может привести к ошибкам, которые могут быть предотвращены на этапе компиляции в Java. Однако, другие разработчики утверждают, что этот подход снижает количество шаблонного кода и упрощает написание программ.

3. Как перенести статичный метод из Java в Kotlin?

В Kotlin нет статических методов, для этих целей обычно служит companion object. Для того чтобы метод из Java был представлен как статический используется аннотация @JvmStatic. Эта аннотация говорит компилятору Kotlin создать статический метод в байт-коде, что позволяет использовать методы так же, как в Java. Например, если у нас есть статический метод в Java: public class MyClass { public static int sum(int a, int b) { return a + b; } } Мы можем использовать этот метод в Kotlin, добавив аннотацию @JvmStatic: object MyClass { @JvmStatic fun sum(a: Int, b: Int): Int { return a + b } }

4. Во что преобразуется internal в Java?

В Java нет эквивалента модификатору доступа internal из Kotlin. При компиляции Kotlin-кода в Java-байткод, модификатор доступа internal преобразуется в модификатор public в Java. Таким образом, все члены класса, отмеченные как internal, будут видны из любого места в том же пакете, а также из любого другого модуля, которому был разрешен доступ к этому модулю. Члены internal классов проходят через искажение имен, чтобы усложнить случайное использование их из Java и позволить перегрузку для членов с одинаковыми сигнатурами, которые не видят друг друга в соответствии с правилами Kotlin.

5. Какие коллекции есть в Kotlin?

Коллекция — это объект, содержащий в себе набор значений одного или различных типов, а также позволяющий к этим значениям обращаться и извлекать. Другими словами — это контейнер, в который вы можете помещать то, что вам нужно, а затем каким-либо образом с ним взаимодействовать. В Kotlin есть три типа коллекций: - List (список). Упорядоченная коллекция, в которой к элементам можно обращаться по их индексам. Идентичные элементы (дубликаты) могут встречаться в списке более одного раза. Примером списка является предложение: это группа слов, их порядок важен, и они могут повторяться. - Set (множество/набор). Неупорядоченная коллекция без повторяющихся значений. Примером множества является алфавит. - Map (словарь/ассоциативный список). Набор из пар "ключ-значение". Ключи уникальны и каждый из них соответствует ровно одному значению. В коллекции могут присутствовать повторяющиеся значения, но не повторяющиеся ключи. Пример — ID сотрудников и их должностей. Map не является наследником интерфейса Collection. Два типа интерфейсов, на основе которых создаются коллекции: - Неизменяемый (read-only) — дают доступ только для чтения (Set, List, Map, Collection). - Изменяемый (mutable) — расширяет предыдущий интерфейс и дополнительно даёт доступ к операциям добавления, удаления и обновления элементов коллекции (MutableSet, MutableList, MutableMap, MutableCollection). List Список — это упорядоченная коллекция. Каждое значение, помещённое в List, называется элементом, к которому можно обращаться по индексу. Индексы начинаются с "0" и заканчиваются индексом последнего элемента в списке — (list.size - 1). Список может содержать сколько угодно одинаковых элементов — дублей (в том числе null). val trees = listOf("Сосна", "Берёза", "Дуб") // неизменяемый список trees.add("Ясень") // ошибка val mutableTrees = mutableListOf("Сосна", "Берёза", "Дуб") // изменяемый список mutableTrees.add("Ясень") // всё ок По умолчанию в Kotlin реализацией List является ArrayList, его можно создать напрямую: val mutableTrees = ArrayList<String>() mutableTrees.add("Ясень") Set Множество — это коллекция уникальных элементов. Это означает, что Set не может содержать дублей. Обратите внимание, что null — это тоже уникальный элемент. val trees = setOf("Сосна", "Берёза", "Дуб") // неизменяемый сет trees.add("Ясень") // ошибка val mutableTrees = mutableSetOf("Сосна", "Берёза", "Дуб") // изменяемый сет mutableTrees.add("Сосна") // проигнорируется В отличие от списка, множество не заботится о порядке элементов. Это означает, что при использовании функций, зависящих от порядка элементов, вы можете получить непредсказуемый результат. Но это зависит от реализации сета. Например, по умолчанию реализацией Set является LinkedHashSet, который сохраняет порядок вставки элементов. val numbers = setOf(1, 2, 3, 4) // по умолчанию LinkedHashSet val numbersBackwards = setOf(4, 3, 2, 1) println(numbers.first() == numbersBackwards.first()) // false println(numbers.first() == numbersBackwards.last()) // true Но также существует HashSet, который не сохраняет порядок вставки элементов. И LinkedHashSet, и HashSet можно создать напрямую. val linkedHashSet = LinkedHashSet<String>() linkedHashSet.add("Дуб") val hashSet = HashSet<String>() hashSet.add("Ясень") Map Ассоциативные списки с уникальными ключами и любыми значениями (дубликаты ключей не допускаются, значения могут быть одинаковыми). Связь между ключами и значениями происходит через специальную форму вызова метода (инфиксный вызов) to. // числа - это ключи, деревья - значения val map = mapOf(1 to "Сосна", 2 to "Берёза", 3 to "Дуб") // неизменяемая мапа map.put(4, "Ясень") // ошибка val mutableMap = mutableMapOf(1 to "Сосна", 2 to "Берёза", 3 to "Дуб") // изменяемая мапа mutableMap.put(4, "Ясень") По умолчанию реализацией мапы является LinkedHashMap, который сохраняет порядок вставки записей. Есть ещё HashMap, которая не сохраняет порядок вставки записей. Обе реализации можно создать напрямую. val linkedHashMap = LinkedHashMap<Int, String>() linkedHashMap.put(1, "Дуб") val hashMap = HashMap<Int, String>() hashMap.put(1, "Ясень")

6. Какая из коллекций не является имплементацией Collection?

Интерфейс Map не является наследником интерфейса Collection. Технически — это не коллекция, так как Map не наследуется от Collection. Но это также структура для хранения данных и ее всегда изучают и рассматривают вместе с коллекциями. В разговоре вполне нормально называть Map коллекцией.

7. Что такое sequences и чем они отличаются от коллекций?

Sequences или последовательности — ещё один тип контейнера в Kotlin, но он не является коллекцией. Последовательности очень похожи на коллекции, они предоставляют те же функции. Ключевая разница в том, что они применяют другой подход с многоэтапной обработкой элементов (например, когда вы последовательно вызываете некую цепочку вызовов к коллекции). Последовательность — это итерируемый тип, с которым можно работать, не создавая ненужных промежуточных коллекций, выполняя все применимые операции над каждым элементом перед переходом к следующему. Отличия коллекции от последовательности: Если обработка Iterable состоит из нескольких шагов, то они выполняются немедленно: при завершении обработки каждый шаг возвращает свой результат — промежуточную коллекцию. Следующий шаг выполняется для этой промежуточной коллекции. Sequence же по возможности выполняет обработку "лениво" — фактически вычисления происходят только тогда, когда запрашивается результат выполнения всех шагов. Iterable завершает каждый шаг для всей коллекции, а затем переходит к следующему шагу. Sequence выполняет все шаги один за другим для каждого отдельного элемента. Iterable могут занимать больше памяти, чем последовательности, так как они вычисляют все элементы сразу и хранят их в памяти. Sequence вычисляют элементы при необходимости и не хранят все элементы в памяти. Зачем вообще нужны Sequences? Для оптимизации производительности в работе с большими коллекциями (от 1000). Фишка в том, что значения в таких коллекциях создаются только по мере необходимости, не инициализируя их заранее. Из-за этого нет доступа к содержимому по индексу, а также не контролируется размер. Последовательности позволяют избежать создания промежуточных результатов для каждого шага, тем самым повышая производительность всей цепочки вызовов. Однако "ленивый" характер последовательностей добавляет некоторые накладные расходы, которые могут быть значительными при обработке небольших коллекций или при выполнении более простых вычислений. Следовательно, вы должны рассмотреть, а затем самостоятельно решить, что вам подходит больше — Sequence или Iterable.

8. Расскажите про проверку на равенство == и equals()

1. Проверка на равенство в Java Структурное равенство (значение) — метод equals(). Ссылочное равенство — оператор ==: — примитивные типы данных: сравнивает значения переменных — ссылочные типы данных (объекты, массивы): сравнивает ссылки 2. Проверка на равенство в Kotlin Структурное равенство (значение) — оператор == (проверка через equals()) Ссылочное равенство — оператор ===: — примитивные типы данных: сравнивает значения переменных — ссылочные типы данных (объекты, массивы): сравнивает ссылки 3. Разница == с Java Структурное равенство (значение) — оператор == в Kotlin это equals() в Java, т.е. в Kotlin строки можно всегда сравнивать через ==. Ссылочное равенство — оператор === в Kotlin это == в Java.

9. Что такое анонимные классы и объекты?

Анонимный класс — это класс, которые явно не объявлен с помощью class, наследуется от заданного класса или реализует заданный интерфейс. Анонимный класс не всегда является синглтоном. Анонимный класс создается каждый раз при вызове соответствующего конструктора и используется только в контексте, где был создан. При этом каждый экземпляр анонимного класса имеет свое уникальное состояние и может отличаться от других экземпляров того же анонимного класса. В Kotlin анонимный класс создается следующим образом: val obj = object : SuperClassOrInterface() { // implementation here } Объекты анонимных классов полезны для одноразового использования. Экземпляры анонимных классов называют анонимными объектами, потому что они объявляются выражением, а не именем. Анонимный объект начинается с ключевого слова object. - можно задавать свойства, функции, блоки инициализации; - можно наследоваться от других классов и реализовывать интерфейсы; - нельзя создавать конструкторы (как основные, так и вторичные). Ключевое слово object позволяет одновременно объявить класс и создать его экземпляр (т.е. объект). При этом применять его можно по-разному: - object Name — это объявление объекта (оbject declaration), реализация паттерна Singleton; - companion object — это объект-компаньон внутри класса (также Singleton); - object — это объект-выражение (анонимный объект/object expression), не Singleton.

10. Расскажите про объявление объекта

Объявляется объект при помощи ключевого слова object, после которого следует имя объекта. Файл, содержащий только object представляет из себя Singleton, т.е. будет создан только один экземпляр этого класса. Пример: object One { val cats = arrayListOf<Cat>() fun callCat() { for (cat in cats) { ... } } } Можно обращаться к методам и свойствам класса через имя объекта: One.cats.add(Cat(...)) One.callCat() Инициализация объявления объекта потокобезопасна и выполняется при первом доступе (лениво).

11. Что такое companion object?

Объекты можно объявлять внутри класса, при этом нет каких-либо ограничений по их количеству. Но только один объект можно пометить ключевым словом companion object в рамках одного класса. Синглтон-свойство companion object достигается за счет того, что он создается внутри класса в качестве статического поля. Он будет инициализирован при первом обращении к нему или при создании первого экземпляра класса, в котором он объявлен. Важно отметить, что companion object будет инициализирован первым, а затем уже будет создан экземпляр класса: class MyClass { init { // Выполняется всегда после инициализации companion object } companion object { init { // Выполняется всегда перед блоком init содержащего класса } } } val myClass = MyClass() Такому объекту можно не указывать свое имя, и обращаться к методам и свойствам объекта через имя содержащего его класса без явного указания имени объекта. class SomeClass { companion object { fun create() } } val someClass = SomeClass.create() Компилируется в public static final class на Java. Работает подобно ключевому слову static в Java.

12. Что такое объект-выражение?

Поддержи проект и получи доступ ко всему контенту всего за 290

13. В чем разница между анонимным и объявляемым объектом?

Поддержи проект и получи доступ ко всему контенту всего за 290

14. Зачем нужна аннотация @JvmStatic?

Поддержи проект и получи доступ ко всему контенту всего за 290

15. Null safety, nullable и non-nullable типы

Поддержи проект и получи доступ ко всему контенту всего за 290

16. Способы проверки значения на null

Поддержи проект и получи доступ ко всему контенту всего за 290

17. От какого класса унаследованы все классы в Kotlin?

Поддержи проект и получи доступ ко всему контенту всего за 290

18. Чем Any в Kotlin отличается от Object в Java?

Поддержи проект и получи доступ ко всему контенту всего за 290

19. Что такое Unit?

Поддержи проект и получи доступ ко всему контенту всего за 290

20. Сколько существует instance Unit (1)?

Поддержи проект и получи доступ ко всему контенту всего за 290

21. Что такое Nothing?

Поддержи проект и получи доступ ко всему контенту всего за 290

22. Подтип всех типов в Kotlin

Поддержи проект и получи доступ ко всему контенту всего за 290

23. Сколько существует instance Nothing (0)?

Поддержи проект и получи доступ ко всему контенту всего за 290

24. Есть ли аналог Nothing в Java?

Поддержи проект и получи доступ ко всему контенту всего за 290

25. Модификаторы доступа в Kotlin

Поддержи проект и получи доступ ко всему контенту всего за 290

26. Разница между var, val, const val

Поддержи проект и получи доступ ко всему контенту всего за 290

27. Расскажите про свойства, методы get и set

Поддержи проект и получи доступ ко всему контенту всего за 290

28. В чем отличие field от property?

Поддержи проект и получи доступ ко всему контенту всего за 290

29. Отложенная и ленивая инициализация свойств

Поддержи проект и получи доступ ко всему контенту всего за 290

30. Что такое делегированные свойства?

Поддержи проект и получи доступ ко всему контенту всего за 290

31. Как реализовать кастомный делегат?

Поддержи проект и получи доступ ко всему контенту всего за 290

32. Типы конструкторов в Kotlin

Поддержи проект и получи доступ ко всему контенту всего за 290

33. Блок инициализации (init блок)

Поддержи проект и получи доступ ко всему контенту всего за 290

34. Что такое Data классы?

Поддержи проект и получи доступ ко всему контенту всего за 290

35. Что такое мульти-декларации (destructuring declarations)?

Поддержи проект и получи доступ ко всему контенту всего за 290

36. Что делает функция componentN()?

Поддержи проект и получи доступ ко всему контенту всего за 290

37. Какие требования должны быть соблюдены для создания data класса?

Поддержи проект и получи доступ ко всему контенту всего за 290

38. Можно ли наследоваться от data класса?

Поддержи проект и получи доступ ко всему контенту всего за 290

39. Что такое абстрактные классы?

Поддержи проект и получи доступ ко всему контенту всего за 290

40. Что такое интерфейс?

Поддержи проект и получи доступ ко всему контенту всего за 290

41. Как выбрать, что применять — абстрактный класс или интерфейс?

Поддержи проект и получи доступ ко всему контенту всего за 290

42. Почему классы в Kotlin по умолчанию final?

Поддержи проект и получи доступ ко всему контенту всего за 290

43. Что нужно сделать, чтобы класс можно было наследовать?

Поддержи проект и получи доступ ко всему контенту всего за 290

44. Как можно получить тип класса?

Поддержи проект и получи доступ ко всему контенту всего за 290

45. Что такое enum класс?

Поддержи проект и получи доступ ко всему контенту всего за 290

46. Что такое sealed класс?

Поддержи проект и получи доступ ко всему контенту всего за 290

47. Какая разница между sealed class и enum?

Поддержи проект и получи доступ ко всему контенту всего за 290

48. Что такое inner (внутренние) и nested (вложенные) классы?

Поддержи проект и получи доступ ко всему контенту всего за 290
Хочешь стать частью сообщества Девстанции?
Вступай в наш чат в Telegram

Вам может быть интересно

Шпаргалка
  15 вопросов

Шпаргалка по Domain-Driven Design

Вопросы и ответы про предметно-ориентированное проектирование

181 просмотр
От 27 января
Викторина
  10 вопросов

Викторина на базовое знание Git

Тест на знание базовых механик Git

66 просмотров
От 30 мая 2023
Шпаргалка
  53 вопроса

Топ 55 вопросов с собеседований по Java

Вопросы для собеседования Java-разработчика

278 просмотров
От 25 февраля
Шпаргалка
  13 вопросов

Общие принципы и понятия ООП

Вопросы для собеседования по теме ООП

198 просмотров
От 7 октября 2023
Шпаргалка
  12 вопросов

Операционные системы: базовые понятия

Потоки, процессы, конкурентность и прочие понятия из мира ОС

202 просмотра
От 27 января
Шпаргалка
  11 вопросов

HTTP, SSL, WebSocket и прочее

Вопросы для собеседования бэкенд-разработчика

238 просмотров
От 12 октября 2023

Топ тредов

Gravatar for 9tokio
Tokio:
то что раньше было бесплатным теперь платное - вот это я понимаю

Последнее сообщение:
Логотип Девстанции
Девстанция:
Спасибо за поддержку проекта :) Повышение качества контента - один из важнейших приоритетов. Этому м...
3 сообщения
213 просмотров

Логотип Девстанции
Девстанция:
Поиск людей для совместной разработки IT-стартапов

Последнее сообщение:
В этом треде пока нет сообщений
0 сообщений
107 просмотров

Логотип Девстанции
Девстанция:
Какой язык программирования выбрать в качестве первого?

Последнее сообщение:
Gravatar for 2kokke
Kokke:
Python или JS - универсально. Но по уму надо бы с чего-то строгого начинать и достаточно низкоуровне...
1 сообщение
139 просмотров

Все категории