Kotlin | Вопросы собесов
2.56K subscribers
30 photos
972 links
Download Telegram
🤔 Как работает HashMap?

HashMap в Kotlin хранит пары ключ-значение и использует хеширование для быстрого поиска и вставки элементов. Каждый ключ хешируется, и результат хеш-функции определяет, где в таблице будет храниться соответствующее значение. В случае коллизий (когда два ключа имеют одинаковый хеш) HashMap использует цепочки или другие методы для хранения нескольких значений в одной корзине. Это обеспечивает доступ к элементам за среднее время O(1).

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥2
🤔 В какой момент генерируется код при использовании SQLite?

Код для работы с SQLite в Android не генерируется автоматически — разработчик сам пишет SQL-запросы и управляет БД.

Но если используется Room (ORM для SQLite), то код генерируется на этапе компиляции с помощью Annotation Processing (kapt) или KSP.

🚩Обычный SQLite – без генерации кода

Если используешь SQLiteOpenHelper, то код не генерируется, ты сам пишешь SQL-запросы:
class MyDatabaseHelper(context: Context) : SQLiteOpenHelper(context, "mydb", null, 1) {
override fun onCreate(db: SQLiteDatabase) {
db.execSQL("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)")
}

override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
db.execSQL("DROP TABLE IF EXISTS users")
onCreate(db)
}
}


🚩Room – код генерируется при компиляции

Если используешь Room, код автоматически генерируется во время компиляции с помощью Annotation Processing (kapt) или KSP.
Ты пишешь аннотации (@Entity, @Dao, @Database).
Room-аннотации анализируются при компиляции (kapt / KSP).
Генерируется SQL-код и DAO-методы.
@Entity
data class User(
@PrimaryKey val id: Int,
val name: String
)

@Dao
interface UserDao {
@Query("SELECT * FROM User")
fun getAllUsers(): List<User>

@Insert
fun insert(user: User)
}

@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
}


🚩Когда именно генерируется код Room?

Если используешь kapt (Annotation Processor) или KSP, то код генерируется во время компиляции.
dependencies {
implementation("androidx.room:room-runtime:2.6.1")
kapt("androidx.room:room-compiler:2.6.1") // Кодогенерация
}


Пример с KSP (быстрее kapt)
dependencies {
implementation("androidx.room:room-runtime:2.6.1")
ksp("androidx.room:room-compiler:2.6.1") // Кодогенерация
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
🤔 В чем отличие горячих и холодных потоков?

– Холодные (cold) — начинают генерировать данные только после подписки (например, Flow, Observable).
– Горячие (hot) — генерируют данные независимо от подписчиков (например, SharedFlow, LiveData, Broadcast).


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥1
🤔 Как собираем код?

Сборка Android-приложения проходит несколько этапов:
Компиляция (.kt/.java → .class → .dex)
Объединение ресурсов (XML, PNG → R.java)
Сборка APK/AAB
Подписывание и оптимизация
Установка и запуск на устройстве

🚩Компиляция кода (`.kt/.java → .dex`)

Компиляция Kotlin/Java в байткод JVM (.class)
Kotlin-код (.kt) → Java-байткод (.class)
Java-код (.java) → .class
- Используются компиляторы:
- kotlinc (Kotlin Compiler)
- javac (Java Compiler)
// Kotlin-код (MainActivity.kt)
fun main() {
println("Привет, Android!")
}

kotlinc MainActivity.kt -d MainActivity.class


Преобразование .class в `.dex*
Android не использует байткод JVM, а преобразует .class в Dalvik Executable (.dex).
d8 MainActivity.class --output classes.dex


🚩Компиляция ресурсов (`XML, PNG → R.java → .dex`)

Android Gradle Plugin (AGP) обрабатывает ресурсы
- res/layout/*.xml → UI файлы
- res/drawable/*.png → Иконки
- AndroidManifest.xml → Метаинформация
public final class R {
public static final class layout {
public static final int activity_main = 0x7f0a0000;
}
}


🚩Сборка APK/AAB

APK (старый формат) и AAB (новый формат Google Play)
classes.dex + res/ + AndroidManifest.xml объединяются
Проходит обфускация (ProGuard / R8)
APK/AAB упаковывается в ZIP-архив
zipalign -v 4 app.apk signed_app.apk


🚩Подписывание и оптимизация

APK/AAB должен быть подписан перед установкой
apksigner sign --ks my-release-key.jks --out signed_app.apk app-release.apk


Установка и запуск
adb install signed_app.apk
adb shell am start -n com.example.app/.MainActivity


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
🤔 Что происходит, когда делаешь ==?

В Kotlin:
- == вызывает equals(), то есть логическое сравнение значений.
- === — это сравнение по ссылке, то есть проверка, указывают ли обе переменные на один и тот же объект в памяти.
В Java: == сравнивает ссылки для объектов, а equals() — содержимое.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥2
🤔 Что такое px, dp, sp?

В Android используются разные единицы измерения для работы с экраном, чтобы адаптировать UI под разные устройства.

🚩`px` (пиксели) – физические точки экрана

px (pixel) – это самая маленькая единица изображения на экране.
Не зависит от плотности экрана → на разных устройствах элементы могут выглядеть слишком маленькими или большими.
<TextView
android:layout_width="100px"
android:layout_height="50px"/>


🚩`dp` (density-independent pixels) – независимые от плотности пиксели

dp (density-independent pixel) – это абстрактная единица измерения, которая адаптируется под плотность экрана (dpi).
Рекомендуется для всех размеров UI, чтобы интерфейс выглядел одинаково на разных устройствах.
<TextView
android:layout_width="100dp"
android:layout_height="50dp"/>


Пример в Kotlin
val sizeInPx = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 100f, resources.displayMetrics
)


🚩`sp` (scale-independent pixels) – масштабируемые пиксели (для текста)

sp (scale-independent pixel) – как dp, но ещё учитывает настройки шрифта пользователя. Используется только для размеров шрифтов.
<TextView
android:text="Привет, мир!"
android:textSize="16sp"/>


Пример в Kotlin
val textSizeInPx = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP, 16f, resources.displayMetrics
)


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🤔 Как передать параметры во фрагмент?

Рекомендуемый способ:
- Создать Bundle, положить туда параметры (putString, putInt и т.д.).
- Установить arguments фрагменту.
- В onCreate() фрагмента извлечь через requireArguments().
Это безопасный способ, поддерживаемый Android-системой (в т.ч. при пересоздании фрагмента).


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2
🤔 Что такое утечки памяти?

Это ситуация, когда приложение выделяет память для каких-либо объектов, но затем не освобождает её, даже когда эти объекты больше не нужны. Это приводит к тому, что используемая память накапливается, что может со временем замедлить работу приложения и привести к его аварийному завершению (крашу) из-за нехватки доступной памяти.

🚩Почему происходят утечки памяти в Android?

В Android утечки памяти могут возникнуть из-за особенностей работы виртуальной машины (ART или Dalvik), а также из-за того, что сборщик мусора (Garbage Collector, GC) не может освободить память для объектов, на которые по-прежнему существуют ссылки. Это происходит в следующих случаях:

🟠Долгоживущие ссылки
Если объект ссылается на другой объект, который больше не нужен, последний не может быть освобождён GC. Например:
Статические ссылки, которые продолжают "удерживать" объект.
Замыкания (closures), которые хранят ссылки на контекст активности.

🟠Неявные ссылки
Некоторые объекты системы Android, такие как Context, View, Handler, хранят ссылки на компоненты приложения (например, Activity), из-за чего их нельзя освободить.

🟠Неправильное использование API
Ошибки, такие как регистрация слушателей (listeners) без последующей отписки, использование таймеров, которые продолжают работать даже после уничтожения активности, и так далее.

🚩Пример утечки памяти

public class MyActivity extends AppCompatActivity {
private static TextView myTextView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

myTextView = findViewById(R.id.my_text_view);
myTextView.setText("Hello, Memory Leak!");
}
}


Исправленный код
public class MyActivity extends AppCompatActivity {
private TextView myTextView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

myTextView = findViewById(R.id.my_text_view);
myTextView.setText("Hello, World!");
}
}


🚩Как избежать утечек памяти?

🟠Избегайте долгоживущих ссылок на объекты активности или контекста
Не используйте static для объектов, ссылающихся на Context или Activity. Используйте WeakReference, если нужно сохранить ссылку, которая не должна блокировать сборщик мусора.

🟠Отключайте слушателей и callback-методы
Если вы регистрируете слушателей (например, через setOnClickListener), обязательно удаляйте их в методах жизненного цикла, например, в onDestroy().

🟠Осторожно используйте анонимные классы и лямбда-выражения
Анонимные классы (например, Runnable, Handler) могут неявно хранить ссылки на внешние классы, что может привести к утечке памяти.

🟠Используйте инструменты для выявления утечек памяти
Android Profiler: встроенный инструмент Android Studio для мониторинга использования памяти. LeakCanary: библиотека, которая автоматически обнаруживает утечки памяти в вашем приложении.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1🔥1
🤔 Для чего нужен объект Job?

Job — это элемент управления жизненным циклом корутины. С его помощью можно:
- отменять корутину;
- отслеживать завершение;
- объединять с другими задачами;
- управлять родительскими и дочерними корутинами.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
🤔 Что такое Activity и для чего это используется?

Это компонент приложения, который предоставляет пользовательский интерфейс (UI), с которым пользователи могут взаимодействовать для выполнения различных действий, таких как набор номера телефона, просмотр фотографий, отправка электронной почты и т. д. Каждая активность представляет собой один экран с пользовательским интерфейсом. Если представить приложение как книгу, то активность будет одной страницей этой книги.

🚩Основное назначение

🟠Предоставление интерфейса пользователя
Основная задача — предоставить макет (layout), который будет содержать все элементы пользовательского интерфейса, такие как кнопки, текстовые поля, изображения и прочее, с которыми пользователь может взаимодействовать.

🟠Взаимодействие с пользователем
Служит в качестве "лица" приложения для взаимодействия с пользователем, обрабатывая пользовательские входные данные, такие как нажатие кнопок, ввод текста и т. д.

🟠Управление жизненным циклом
Android управляет активностями через заданный жизненный цикл, который определяет, как активность создается, запускается, останавливается и уничтожается. Разработчики могут переопределять методы жизненного цикла, чтобы добавить свою логику обработки для разных состояний активности.

🟠Переход между экранами
В приложении обычно есть несколько активностей, и он используется для перехода от одного экрана к другому. Для перехода между активностями используются интенты (Intents), которые не только помогают открыть новую активность, но и могут передавать данные между активностями.

🟠Взаимодействие с другими компонентами приложения
М
ожет взаимодействовать с другими компонентами приложения, такими как Services, BroadcastReceivers, и ContentProviders, используя интенты и другие механизмы Android для межкомпонентного взаимодействия.

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
🤔 Можно ли переопределить конструкторы в Java?

Конструкторы не переопределяются, потому что они не наследуются. Однако можно перегружать их в одном классе (разные параметры), и вызывать конструкторы суперкласса через super().


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
🤔 Какие способы навигации знаешь?

В Android есть несколько способов навигации между экранами. Давай разберём основные.

🟠Activity-based навигация
Каждый экран – это отдельная Activity, переход осуществляется с помощью Intent.
val intent = Intent(this, SecondActivity::class.java)
startActivity(intent)


🟠Fragment-based навигация
Один Activity содержит несколько Fragment, навигация через FragmentManager.
supportFragmentManager.beginTransaction()
.replace(R.id.container, SecondFragment())
.addToBackStack(null)
.commit()


🟠Navigation Component (Jetpack)
Google рекомендует Navigation Component для удобной работы с Fragment.
findNavController().navigate(R.id.action_firstFragment_to_secondFragment)


🟠Bottom Navigation / Tab Navigation
Используется BottomNavigationView или TabLayout для переключения между экранами.
bottomNavigationView.setOnNavigationItemSelectedListener { item ->
when (item.itemId) {
R.id.home -> replaceFragment(HomeFragment())
R.id.profile -> replaceFragment(ProfileFragment())
}
true
}


🟠Drawer Navigation (Navigation Drawer)
Боковое меню (DrawerLayout) с пунктами навигации.
drawerLayout.openDrawer(GravityCompat.START)


🟠Deep Links и App Links
Навигация через ссылки (например, myapp://profile/123).
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<data android:scheme="myapp" android:host="profile"/>
</intent-filter>


🟠Navigation в Jetpack Compose
Используется NavHost и NavController.
NavHost(navController, startDestination = "home") {
composable("home") { HomeScreen(navController) }
composable("profile") { ProfileScreen(navController) }
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
🤔 Что такое multibinding в Dagger?

Multibinding позволяет создать коллекции зависимостей одного типа — например, Set или Map. Это особенно полезно для регистрации нескольких обработчиков событий, плагинов или реализаций одного интерфейса.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Для проектов в которых есть несколько модулей, там может быть много Android Manifest'ов, для чего это делается?

В многомодульных проектах каждый модуль может иметь свой AndroidManifest.xml, чтобы:
Задавать зависимости (uses-permission, uses-feature) для конкретного модуля.
Определять компоненты (Activity, Service, BroadcastReceiver) для каждого модуля.
Автоматически объединять манифесты всех модулей в AndroidManifest.xml главного (app) модуля.

🚩Как объединяются манифесты в многомодульном проекте?

При сборке Gradle автоматически сливает (merge) все AndroidManifest.xml в один итоговый файл.
app/  
├── src/main/AndroidManifest.xml ← Главный манифест
├── java/com/example/MainActivity.kt
├── res/
├── build.gradle
feature_login/
├── src/main/AndroidManifest.xml ← Манифест модуля `login`
├── java/com/example/login/LoginActivity.kt
├── res/
├── build.gradle
feature_chat/
├── src/main/AndroidManifest.xml ← Манифест модуля `chat`
├── java/com/example/chat/ChatActivity.kt
├── res/
├── build.gradle


🚩Как работает объединение манифестов?

При сборке манифесты модулей сливаются в манифест главного модуля.
<manifest package="com.example.app">
<application>
<activity android:name=".MainActivity" />
</application>
</manifest>


feature_login (feature_login/src/main/AndroidManifest.xml)
<manifest>
<application>
<activity android:name=".login.LoginActivity" />
</application>
</manifest>


feature_chat (feature_chat/src/main/AndroidManifest.xml)
<manifest>
<application>
<activity android:name=".chat.ChatActivity" />
</application>
</manifest>


После объединения итоговый AndroidManifest.xml выглядит так
<manifest package="com.example.app">
<application>
<activity android:name=".MainActivity" />
<activity android:name=".login.LoginActivity" />
<activity android:name=".chat.ChatActivity" />
</application>
</manifest>


🚩Зачем модулям свой `AndroidManifest.xml`?

🟠Разные разрешения (`uses-permission`) для каждого модуля
Например, модуль camera требует CAMERA, но другие модули — нет.
<uses-permission android:name="android.permission.CAMERA" />


🟠Разные `Activity`, `Service`, `BroadcastReceiver` в каждом модуле
Каждый модуль добавляет только свои компоненты (например, LoginActivity в feature_login).

🟠Разные зависимости для разных модулей
Например, модуль feature_map использует Google Maps, но feature_login — нет.
<uses-library android:name="com.google.android.maps" />


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
🤔 Библиотека для нахождения утечек памяти

На Android популярная библиотека для выявления утечек памяти — LeakCanary от Square. Она отслеживает потенциальные утечки (Activity, Fragment, Context, View) и уведомляет разработчика при обнаружении утечки с подробной трассировкой.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4👍2
🤔 Зачем нужен DiffUtil?

DiffUtil — это утилита для быстрого обновления списков в RecyclerView. Она сравнивает старый и новый список и находит различия, чтобы обновлять только изменённые элементы, а не весь список.

🚩Проблема без `DiffUtil`

Обычное обновление списка без DiffUtil перерисовывает всё, даже если изменился один элемент.
adapter.notifyDataSetChanged() // Полностью обновляет список 


🟠Решение с `DiffUtil`
DiffUtil находит различия между старым и новым списком и обновляет только изменённые элементы.
class MyDiffUtilCallback(
private val oldList: List<User>,
private val newList: List<User>
) : DiffUtil.Callback() {

override fun getOldListSize() = oldList.size
override fun getNewListSize() = newList.size

override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList[oldItemPosition].id == newList[newItemPosition].id
}

override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList[oldItemPosition] == newList[newItemPosition] // Используем data class (авто `equals()`)
}
}


🚩Как использовать `DiffUtil` в `RecyclerView.Adapter`?

После создания DiffUtil.Callback, вызываем DiffUtil.calculateDiff() и передаём результат в adapter.
fun updateList(newList: List<User>) {
val diffCallback = MyDiffUtilCallback(userList, newList)
val diffResult = DiffUtil.calculateDiff(diffCallback)

userList = newList // Обновляем старый список
diffResult.dispatchUpdatesTo(this) // Обновляем только изменённые элементы
}


🟠`ListAdapter` – ещё проще!
Если используем ListAdapter, DiffUtil уже встроен.
class UserAdapter : ListAdapter<User, UserViewHolder>(DIFF_CALLBACK) {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_user, parent, false)
return UserViewHolder(view)
}

override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
holder.bind(getItem(position)) // `getItem()` уже работает с `ListAdapter`
}

companion object {
private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<User>() {
override fun areItemsTheSame(oldItem: User, newItem: User): Boolean =
oldItem.id == newItem.id

override fun areContentsTheSame(oldItem: User, newItem: User): Boolean =
oldItem == newItem
}
}
}


Обновление списка в ListAdapter
adapter.submitList(newList) // DiffUtil работает внутри 🚀


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
🤔 Какие есть особенности использования Nothing в дженериках

Nothing в Kotlin используется как нижняя граница для дженериков, что означает, что он совместим с любым типом, но не может иметь значений. Это позволяет указывать, что функция или выражение не возвращают никакого значения, например, в случае исключений или бесконечного цикла. Nothing удобно использовать в дженериках для создания функций, которые гарантированно завершат выполнение программы или выбросят исключение.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
🤔 В каких случаях используют atomic, в каких synchronized?

В Kotlin для работы с многопоточностью можно использовать atomic переменные или synchronized блоки. Они помогают избежать гонок данных (race conditions), когда несколько потоков одновременно изменяют одну и ту же переменную.

🚩Когда использовать `atomic` переменные?

Atomic переменные (AtomicInteger, AtomicLong, AtomicReference и др.) используются, когда нужно быстро и безопасно обновлять одно значение без блокировки потока.
Высокая производительность – атомарные операции работают быстрее, чем synchronized.
Потокобезопасность – операции выполняются без блокировок (lock-free).
Удобство – простые методы incrementAndGet(), compareAndSet() и т. д.
Работает только с одним значением – не подходит для сложных операций.
Не подходит для зависимых изменений (например, если изменение одной переменной зависит от другой).

import java.util.concurrent.atomic.AtomicInteger

val counter = AtomicInteger(0)

fun increment() {
counter.incrementAndGet() // Увеличиваем значение безопасно
}


🟠Когда использовать `synchronized`?
Используется, когда нужно защитить сразу несколько связанных операций от одновременного выполнения в нескольких потоках.
Подходит для сложных операций с несколькими переменными.
Работает с любыми типами данных.
Снижает производительность – потоки ждут, пока один поток закончит работу.
Может вызывать deadlock (взаимную блокировку).
val lock = Any()
var count = 0

fun increment() {
synchronized(lock) {
count++ // Только один поток может изменять `count` одновременно
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
🤔 Как SVG-строку показать в виде векторного файла?

– Сохранить строку как *.svg в файл и загрузить через SvgDecoder,
– Использовать библиотеки (Glide, Coil, androidsvg),
– Преобразовать в Drawable и отобразить через ImageView.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥1💊1
🤔 Что при создании классов в Kotlin изменились по сравнению с Java?

При создании классов по сравнению с Java произошли несколько значительных изменений и упрощений. Kotlin предлагает более лаконичный и выразительный синтаксис, что делает код более читаемым и удобным.

🚩Объявление классов и конструкторов

В Kotlin объявление классов и их конструкторов значительно упрощено.
В Java
public class Person {
private String name;
private int age;

public Person(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public int getAge() {
return age;
}
}


В Kotlin
class Person(val name: String, val age: Int)


🟠Статические члены
В Java для объявления статических членов используется ключевое слово static. В Kotlin вместо этого используются companion object.
В Java
public class MyClass {
public static final String CONSTANT = "constant";

public static void staticMethod() {
// Some code
}
}


В Kotlin
class MyClass {
companion object {
const val CONSTANT = "constant"

@JvmStatic
fun staticMethod() {
// Some code
}
}
}


🟠Data классы
Kotlin предоставляет специальный тип классов — data классы, которые автоматически генерируют методы equals(), hashCode(), toString(), copy(), и componentN().
В Java
public class User {
private String name;
private int age;

public User(String name, int age) {
this.name = name;
this.age = age;
}

@Override
public boolean equals(Object o) {
// Implementation
}

@Override
public int hashCode() {
// Implementation
}

@Override
public String toString() {
// Implementation
}
}


В Kotlin
data class User(val name: String, val age: Int)


🟠Свойства и методы доступа
В Kotlin свойства объявляются напрямую, и методы доступа (геттеры и сеттеры) генерируются автоматически.
В Java
public class Rectangle {
private int width;
private int height;

public int getWidth() {
return width;
}

public void setWidth(int width) {
this.width = width;
}

public int getHeight() {
return height;
}

public void setHeight(int height) {
this.height = height;
}
}


В Kotlin
class Rectangle(var width: Int, var height: Int)


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1