uz
Feedback
Kotlin | Вопросы собесов

Kotlin | Вопросы собесов

Kanalga Telegram’da o‘tish
2 492
Obunachilar
Ma'lumot yo'q24 soatlar
-97 kunlar
-830 kunlar
Postlar arxiv
🤔 Что обычно происходит в методе onCreate? Происходит инициализация UI, зависимостей, подписка на данные, обработка Intent, создание ViewModel. Это точка входа, где активити готовится к отображению. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Расскажи про коллекцию Map Map – это коллекция пар ключ-значение. Каждый ключ уникален, а значения могут повторяться. В Kotlin Map не наследуется от Collection, но является частью стандартных коллекций. 🟠Виды `Map` в Kotlin В Kotlin есть два основных типа Map: Map (неизменяемая) – нельзя добавлять/удалять элементы после создания. MutableMap (изменяемая) – можно добавлять, удалять и изменять элементы. Создаётся с помощью mapOf()
val users = mapOf(1 to "Alice", 2 to "Bob", 3 to "Charlie")
println(users[1])  // Выведет: Alice
Создаётся с помощью mutableMapOf()
val users = mutableMapOf(1 to "Alice", 2 to "Bob")
users[3] = "Charlie"  // Добавляем элемент
users[1] = "Alex"  // Изменяем значение по ключу
users.remove(2)  // Удаляем элемент
println(users)  // {1=Alex, 3=Charlie}
🟠Основные операции с `Map` map[key] – получить значение (или null, если ключа нет). map.getValue(key) – получить значение (или исключение, если ключа нет). map.getOrDefault(key, defaultValue) – вернуть значение или defaultValue, если ключа нет. map.getOrElse(key) { default } – если ключа нет, выполнить лямбда-выражение.
val users = mapOf(1 to "Alice", 2 to "Bob")
println(users[1])  // Alice
println(users.getOrDefault(3, "Unknown"))  // Unknown
🟠Проверка наличия ключей и значений map.containsKey(key) – есть ли ключ? map.containsValue(value) – есть ли значение?
println(users.containsKey(2))  // true
println(users.containsValue("Charlie"))  // false
Перебор элементов
for ((key, value) in users) {
    println("ID: $key, Name: $value")
}
Фильтрация Map
val filtered = users.filter { (key, value) -> key % 2 == 0 }
println(filtered)  // {2=Bob}
🚩Особенности `Map` в Kotlin 🟠Порядок элементов mapOf() – не гарантирует порядок. linkedMapOf() – сохраняет порядок добавления. 🟠Производительность Обычный HashMap (mutableMapOf()) – O(1) для поиска по ключу. TreeMapO(log n), но поддерживает сортировку по ключам.
val sortedUsers = sortedMapOf(3 to "Charlie", 1 to "Alice", 2 to "Bob")
println(sortedUsers)  // {1=Alice, 2=Bob, 3=Charlie}
Ставь 👍 и забирай 📚 Базу знаний

🤔 Что является сущностью корутин контекста? Корутин контекст в Kotlin определяет настройки и правила для выполнения корутин, включая диспетчер, который управляет тем, на каком потоке будет выполняться корутина, а также другие элементы, такие как Job для управления жизненным циклом корутины. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Какие есть методы у класса Object? В Java класс Object является корневым классом для всех остальных классов. Это значит, что все классы в Java неявно наследуются от Object, если явно не указано другое. 🚩Основные методы класса `Object` 🟠`equals(Object obj)` Определяет, равны ли два объекта. По умолчанию использует сравнение по ссылке (==), но может быть переопределён для логического сравнения.
     class Person {
         String name;
         
         Person(String name) {
             this.name = name;
         }
         
         @Override
         public boolean equals(Object obj) {
             if (this == obj) return true;
             if (obj == null || getClass() != obj.getClass()) return false;
             Person person = (Person) obj;
             return name.equals(person.name);
         }
     }

     public class Main {
         public static void main(String[] args) {
             Person p1 = new Person("Alice");
             Person p2 = new Person("Alice");
             System.out.println(p1.equals(p2)); // true
         }
     }
     
🟠`hashCode()` Возвращает числовой хеш-код объекта, используемый, например, в HashMap. Если переопределяем equals(), нужно переопределить и hashCode().
     @Override
     public int hashCode() {
         return Objects.hash(name);
     }
     
🟠`toString()` Возвращает строковое представление объекта. По умолчанию – имя класса + хеш-код, но лучше переопределять.
     @Override
     public String toString() {
         return "Person{name='" + name + "'}";
     }
     
🟠`getClass()` Возвращает объект Class, описывающий класс объекта.
     System.out.println(p1.getClass().getName()); // Person
     
🟠`clone()` Создаёт копию объекта (поверхностное клонирование). Объект должен реализовать Cloneable, иначе будет CloneNotSupportedException.
     class Person implements Cloneable {
         String name;
         
         Person(String name) {
             this.name = name;
         }
         
         @Override
         protected Object clone() throws CloneNotSupportedException {
             return super.clone();
         }
     }
     
🟠`finalize()` *(устарел, не рекомендуется использовать)* Вызывается перед удалением объекта сборщиком мусора. Лучше использовать try-with-resources и close().
     @Override
     protected void finalize() throws Throwable {
         System.out.println("Object is being garbage collected");
     }
     
🟠`wait()`, `notify()`, `notifyAll()` Методы для работы с многопоточностью. wait() – приостанавливает поток до вызова notify(). notify() – пробуждает один поток. notifyAll() – пробуждает все потоки.
     class SharedResource {
         synchronized void doWait() throws InterruptedException {
             wait();
         }
         
         synchronized void doNotify() {
             notify();
         }
     }
Ставь 👍 и забирай 📚 Базу знаний

🤔 Что в inline-функциях можно делать с дженериками? В inline-функциях дженерики сохраняют свои типы, что позволяет использовать операции проверки типов (is, as) и рефлексию. Это делает inline-функции более мощными, чем обычные функции, где происходит стирание типов. Например, вы можете динамически вызывать методы дженерика или создавать экземпляры, основываясь на его типе. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Расскажи все типы данных в Java/Kotlin? В Java и Kotlin существуют различные типы данных, которые можно разделить на две основные категории: Примитивные типы данных (primitive types) Ссылочные типы данных (reference types) 🚩Типы данных в Java 🟠Ссылочные типы данных (Reference Types) Ссылочные типы данных указывают на объекты. Они хранятся в куче (heap) и содержат ссылку (адрес) на объект. Примеры ссылочных типов 🟠Строки (`String`) String str = "Hello"; 🟠Классы и объекты MyClass obj = new MyClass(); 🟠Массивы int[] arr = {1, 2, 3}; 🟠Интерфейсы List<Integer> list = new ArrayList<>(); 🚩Типы данных в Kotlin В Kotlin типы данных делятся на nullable и non-nullable (значения, которые могут быть null, и те, которые не могут). Kotlin избегает примитивных типов напрямую, но на уровне JVM использует их для оптимизации. 🟠Примитивные типы данных (на уровне JVM) Kotlin предоставляет высокоуровневые обёртки для примитивных типов. Например: Int вместо int Double вместо double 🟠Ссылочные типы данных (Reference Types) В Kotlin все данные — объекты. Сюда входят: Строки (String): val str: String = "Hello" Коллекции: val list: List<Int> = listOf(1, 2, 3) Классы: val obj = MyClass() Nullable-типизация: В Kotlin можно указать, что переменная может быть null. Для этого используется ?.
  val nullableString: String? = null
  val nonNullableString: String = "Hello"
  
Интерфейсы и абстракции: Kotlin поддерживает классы, интерфейсы и их реализации, например
  interface Animal {
      fun makeSound()
  }

  class Dog : Animal {
      override fun makeSound() {
          println("Woof!")
      }
  }
  
🟠Тип Unit и Nothing Kotlin добавляет уникальные типы, которые отсутствуют в Java: Unit Эквивалент void в Java, но является объектом. Используется, когда функция ничего не возвращает:
  fun printMessage(message: String): Unit {
      println(message)
  }
  
Nothing Представляет значение, которое никогда не будет существовать (например, функция всегда бросает исключение):
  fun fail(message: String): Nothing {
      throw IllegalArgumentException(message)
  }
Ставь 👍 и забирай 📚 Базу знаний

🤔 Что такое анонимный класс? Анонимный класс — это локальный класс без имени, определённый и созданный одновременно. Обычно используется для одноразовой реализации интерфейса или класса, особенно для обработчиков событий или колбэков. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Опиши модель взаимодействия MVC В модели MVC: - Model отвечает за данные и бизнес-логику. - View отображает данные. - Controller принимает пользовательский ввод, взаимодействует с моделью и обновляет представление. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Как добавить контекст в метод из Dagger Hilt? Hilt позволяет внедрять контекст с помощью аннотаций @ApplicationContext или @ActivityContext, чтобы точно указать, какой именно контекст требуется для зависимости. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Какое главное отличие между Java и Kotlin касательно абстрактных классов и методов? В Kotlin абстрактные классы и методы по умолчанию open, что позволяет их переопределять без явного указания модификатора open. В Java абстрактные методы всегда подразумевают переопределение, а обычные методы должны быть явно помечены abstract или final. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Как бороться с проблемой backpressure в RxJava? Проблема решается использованием Flowable вместо Observable, поскольку Flowable поддерживает стратегию управления нагрузкой. Также применяются операторы onBackpressureBuffer, onBackpressureDrop, onBackpressureLatest и управление запросами вручную. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Что известно про companion object в Kotlin? companion object — это объект внутри класса, позволяющий реализовывать аналог статических методов/свойств. Все члены companion доступны через имя класса без создания экземпляра. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Сложно ли фиксить проблему перегрузки основного потока? Зависит от масштаба: если нагрузка известна (сетевые запросы, тяжёлые вычисления), достаточно вынести в Coroutine, AsyncTask, Executor, HandlerThread или ViewModelScope. Сложность появляется, если всё размазано по UI-слою без изоляции логики. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Как обрабатываются ошибки в Java и как с ними работать? Через конструкции try-catch-finally. Исключения можно перехватывать, пробрасывать (throws), создавать свои (extends Exception), логировать и обрабатывать. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Что такое SharedFlow и чем он отличается от StateFlow? В Kotlin Flow есть два специальных вида потоков для управления состоянием и передачей данных: StateFlow — используется для хранения и отслеживания состояния. SharedFlow — используется для многократной отправки данных нескольким подписчикам. Теперь разберёмся в деталях. 🚩Что такое SharedFlow? SharedFlow — это горячий (hot) поток, который можно использовать для передачи данных нескольким подписчикам. Он не хранит состояние и просто раздаёт значения подписчикам в реальном времени. 🚩Как работает SharedFlow? - Позволяет многим подписчикам получать одни и те же данные. - Может буферизировать значения (хранить их для новых подписчиков). - Может повторять последние значения (replay) для новых подписчиков. - Может накапливать данные и работать как очередь событий.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

fun main() = runBlocking {
    val sharedFlow = MutableSharedFlow<Int>(replay = 2) // Будет повторять последние 2 значения для новых подписчиков

    launch {
        for (i in 1..5) {
            sharedFlow.emit(i)
            delay(100)
        }
    }

    launch {
        delay(150) // Подписываемся чуть позже
        sharedFlow.collect { println("Первый подписчик получил: $it") }
    }

    launch {
        delay(300) // Подписываемся ещё позже
        sharedFlow.collect { println("Второй подписчик получил: $it") }
    }
}
🚩Что такое StateFlow? StateFlow — это поток, который всегда хранит одно последнее значениЕ. Он идеально подходит для представления состояния (например, UI-состояния в MVVM). - Всегда содержит одно актуальное значение. - Если новое значение не отличается от текущего, оно не отправляется подписчикам. - Новый подписчик сразу получает текущее значение. - Можно думать о StateFlow как о LiveData, но для корутин.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

fun main() = runBlocking {
    val stateFlow = MutableStateFlow(0) // Начальное состояние

    launch {
        delay(200) // Подписываемся позже
        stateFlow.collect { println("Подписчик получил: $it") }
    }

    delay(100)
    stateFlow.value = 1 // Меняем состояние
    stateFlow.value = 2 // Меняем состояние
}
Ставь 👍 и забирай 📚 Базу знаний

🤔 Можно ли создать data class без свойства (пустой)? Нет, data class требует хотя бы одного свойства в первичном конструкторе. 1. Это связано с тем, что data class автоматически генерирует методы, которые зависят от свойств (equals, hashCode, toString). 2. Пустой data class не имеет смысла, так как он не будет выполнять свою основную задачу — представление данных. Для пустого объекта можно использовать обычный класс без конструктора. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Как используем Modifiers? В Jetpack Compose Modifier управляет внешним видом, поведением и положением компонента. Они применяются цепочкой и могут комбинироваться для настройки размеров, отступов, взаимодействий и анимаций. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Изменится ли объём памяти стека/кучи,если в приложении создано несколько потоков? Да, объём стека изменится, а вот объём кучи останется неизменным (но нагрузка на неё увеличится). 🚩Что происходит со стеком при создании нового потока? Стек (Stack) — это область памяти для локальных переменных и вызовов функций. - У каждого потока (Thread) есть свой отдельный стек. - Размер стека фиксирован и устанавливается при создании потока. - Чем больше потоков, тем больше памяти выделяется под стеки. Если размер стека 1 МБ, и мы создаём 100 потоков, то под стеки уйдёт 100 МБ памяти. 🚩Что происходит с кучей (Heap) при создании потоков? Куча (Heap) — это область памяти для объектов. - Куча общая для всех потоков. - Новый поток не создаёт отдельную кучу, он использует ту же самую. - Но больше потоков → больше создаваемых объектов → больше нагрузка на сборщик мусора (GC). Вывод: Объём кучи не меняется автоматически, но может быстрее заполняться. Ставь 👍 и забирай 📚 Базу знаний

🤔 Как сохранить состояние скролла при пересоздании Activity? 1. Сохранить текущую позицию скролла в onSaveInstanceState. 2. При восстановлении (в onRestoreInstanceState) установить сохранённую позицию через RecyclerView.scrollToPosition или ScrollView.scrollTo. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 С чем связаны ограничения на запуск сервисов? Google постоянно ограничивает работу сервисов в Android, чтобы: Уменьшить расход батареи Оптимизировать использование памяти Защитить пользователя от фоновых процессов, "убивающих" производительность 🟠Запрет на запуск сервисов в фоне (Android 8+) Сервис нельзя запустить из фона, если приложение не активно. startService(Intent) выдаст ошибку, если приложение не на переднем плане. 1. Использовать Foreground Service (с уведомлением). 2. Использовать JobIntentService / WorkManager.
class MyForegroundService : Service() {
    override fun onCreate() {
        super.onCreate()
        val notification = NotificationCompat.Builder(this, "channelId")
            .setContentTitle("Сервис работает")
            .setSmallIcon(R.drawable.ic_launcher_foreground)
            .build()
        
        startForeground(1, notification) // Запускаем сервис в Foreground
    }
    
    override fun onBind(intent: Intent?): IBinder? = null
}
🟠Запрет на старт сервисов из фона (Android 10+) Если сервис запущен из фона (например, через BroadcastReceiver), он не запустится. Исключение – если сервис работает в Foreground или с AlarmManager. 1. Использовать WorkManager (лучший вариант). 2. Использовать Foreground Service с уведомлением. 3. Использовать AlarmManager для периодических задач. 🟠Ограничение работы сервисов в спящем режиме (Doze Mode, Android 6+) В спящем режиме (Doze Mode) система отключает сервисы. Приложения не могут выполнять фоновые задачи. Использовать Foreground Service. Использовать JobScheduler / WorkManager. Использовать Firebase Cloud Messaging (FCM) для пробуждения приложения. 🟠Запрет на работу сервисов после закрытия приложения (Android 9+) Если пользователь смахнул приложение из списка недавних, фоновые сервисы будут убиты. Решение → Foreground Service + startForeground() или JobScheduler. Ставь 👍 и забирай 📚 Базу знаний