965 просмотров
От 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.

Логотип ДевстанцииАвторизуйтесь, чтобы просматривать следующий контент
13

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
14

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
15

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
16

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
17

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
18

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
19

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
20

Что такое Unit?

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
21

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
22

Что такое Nothing?

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
23

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
24

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
25

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
26

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
27

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
28

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
29

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
30

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
31

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
32

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
33

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
34

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
35

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
36

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
37

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
38

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
39

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
40

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
41

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
42

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
43

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
44

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
45

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
46

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
47

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
48

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
49

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

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
Хотите стать частью сообщества Девстанции?
Вступайте в наш чат в Telegram

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

Вопросник
  15 вопросов

Вопросы с собеседований по DDD

Ответы на вопросы про Domain-Driven Design

572 просмотра
От 4 июня
Вопросник
  11 вопросов

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

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

655 просмотров
От 12 октября 2023
Викторина
  10 вопросов

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

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

148 просмотров
От 30 мая 2023
Вопросник
  13 вопросов

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

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

500 просмотров
От 7 октября 2023
Вопросник
  20 вопросов

Вопросы про Git на собеседовании

Топ вопросов, которые задают на собеседовании про Git

736 просмотров
От 4 июня
Вопросник
  12 вопросов

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

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

508 просмотров
От 27 января

Топ тредов

: Предложите идею и получите спонсорский доступ на месяц

Последнее сообщение:
: Ой, не увидела. Круто, спасибо!
8 сообщений
185 просмотров

: Можно добавить таймер на решение задач

Последнее сообщение:
: да, с момента открытия и до успешных тестов. Чтобы трекать время выполнения )
3 сообщения
116 просмотров

Gravatar for 253malvina
Malvina
: Добавьте angular раздел

Последнее сообщение:
: Раздел открыт!
3 сообщения
137 просмотров

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