Kotlin | Вопросы собесов
2.56K subscribers
28 photos
966 links
Download Telegram
🤔 Что можно делать через Composer?

Это внутренний компонент Compose, отвечающий за управление состоянием и рендерингом. Через него Compose отслеживает изменения в UI и обновляет только те элементы, которые изменились. Он также управляет процессом "recomposition".


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

Класс-наследник в Kotlin получает доступ к функционалу родительского класса через:
Наследование (:) — доступ ко всем open методам и свойствам.
Ключевое слово super — вызов методов родителя.
Переопределение (override) — изменение поведения.

🚩Наследование: доступ к методам и свойствам

Класс-наследник получает доступ ко всем open методам и свойствам родителя.
open class Animal(val name: String) {
fun eat() {
println("$name ест")
}
}

class Dog(name: String) : Animal(name)

fun main() {
val dog = Dog("Шарик")
dog.eat() // Шарик ест (метод унаследован)
}


🚩`super` – вызов методов родителя

Пример
open class Animal {
open fun makeSound() {
println("Животное издаёт звук")
}
}

class Dog : Animal() {
override fun makeSound() {
super.makeSound() // Вызываем метод родителя
println("Гав-гав!")
}
}

fun main() {
val dog = Dog()
dog.makeSound()
}


Вывод
Животное издаёт звук
Гав-гав!


🚩Переопределение (`override`)

Класс-наследник может изменить поведение родительского метода.
open class Animal {
open fun move() {
println("Животное двигается")
}
}

class Bird : Animal() {
override fun move() {
println("Птица летит") // Переопределяем метод
}
}

fun main() {
val bird = Bird()
bird.move() // Птица летит
}


🚩Вызов конструктора родителя (`super`)

Пример
open class Animal(val name: String)

class Dog(name: String, val breed: String) : Animal(name) {
fun info() {
println("Имя: $name, Порода: $breed") // Используем `name` из родителя
}
}

fun main() {
val dog = Dog("Бобик", "Лабрадор")
dog.info() // Имя: Бобик, Порода: Лабрадор
}


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

dp (Density-independent Pixels) — это единица измерения в Android, используемая для создания адаптивных интерфейсов. Она масштабируется в зависимости от плотности экрана устройства, обеспечивая одинаковый визуальный размер элементов на разных экранах.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥2😁1
🤔 Опиши как лучше всего использовать модификаторы доступа в Java?

В Java есть 4 модификатора доступа, которые контролируют видимость полей, методов и классов:

🚩`private` – самый безопасный (использовать по умолчанию)

Поля почти всегда должны быть private, чтобы инкапсулировать данные. Методы тоже лучше делать private, если они не должны использоваться извне.
public class User {
private String name; // Доступен только внутри класса

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

private void logUserAction() { // Только внутри класса
System.out.println(name + " совершил действие");
}
}


🚩`package-private` (без модификатора) – для классов внутри пакета

Используется, если класс не должен быть доступен за пределами пакета. Полезно для вспомогательных классов.
class FileHelper { //  Доступен только в этом пакете
static void readFile(String path) {
System.out.println("Читаем файл: " + path);
}
}


🚩`protected` – для наследников, но не для всех

protected лучше использовать только в abstract классах и для методов, которые должны быть переопределены. Не используй protected для полей → нарушает инкапсуляцию!
abstract class Animal {
protected void makeSound() { // Наследники могут переопределять
System.out.println("Какой-то звук");
}
}

class Dog extends Animal {
@Override
protected void makeSound() {
System.out.println("Гав-гав!");
}
}


🚩`public` – только если класс/метод нужен везде

Класс можно делать public, только если он должен быть доступен во всех пакетах. Не делай поля public → нарушает инкапсуляцию!
public class UserManager { //  Доступен везде
public void createUser() { // Можно вызывать в любом месте
System.out.println("Создание пользователя...");
}
}


🚩`final` и `static` – дополняем модификаторы

final class → класс нельзя наследовать.
final method → метод нельзя переопределить.
final field → переменная неизменяема (константа).
public final class MathUtils {
public static final double PI = 3.14159;
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
🤔 Что известно про stable?

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


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

Если удалился элемент из списка, нужно:
Удалить его из списка данных.
Сообщить Adapter, чтобы он перерисовал только изменённые элементы.

🚩Используем `notifyItemRemoved()` (лучший вариант)

Этот метод обновляет только удалённый элемент, сохраняя анимации.
fun removeItem(position: Int) {
itemList.removeAt(position) // Удаляем из списка данных
notifyItemRemoved(position) // Сообщаем адаптеру
notifyItemRangeChanged(position, itemList.size) // Обновляем индексы
}


🚩Если изменился весь список – `DiffUtil`

Если изменился несколько элементов, лучше использовать DiffUtil, чтобы обновить только нужные элементы.
class MyAdapter : ListAdapter<Item, MyViewHolder>(DIFF_CALLBACK) {

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

override fun areContentsTheSame(oldItem: Item, newItem: Item): Boolean {
return oldItem == newItem
}
}
}
}


Обновляем список через submitList()
fun removeItem(item: Item) {
val newList = currentList.toMutableList()
newList.remove(item)
submitList(newList) // `DiffUtil` сам вычислит, что обновить
}


🚩Полное обновление списка (`notifyDataSetChanged()`)

Использовать только если изменился весь список!
fun removeItem(position: Int) {
itemList.removeAt(position)
notifyDataSetChanged() // Перерисовывает весь список (медленно)
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
🤔 Что из себя представляет Flow?

Это асинхронный поток данных, который работает как List, но лениво.
Особенности:
- Выдает значения последовательно – одно за другим.
- Не блокирует поток – работает с suspend-функциями.
- Поддерживает cancel() – может быть остановлен в любой момент.
- Позволяет работать с бесконечными потоками – полезно для сетевых запросов, БД, UI-событий.


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

В Android есть два основных типа потоков:
1. UI Thread (главный поток) → отвечает за интерфейс и обработку событий.
2. Worker Thread (фоновый поток) → используется для долгих операций (запросы в сеть, работа с БД).

🚩`UI Thread` – главный поток

- Отвечает за отрисовку интерфейса (Activity, Fragment, View).
- Обрабатывает нажатия, свайпы, анимации.
- Все setText(), setImageResource() и другие UI-методы работают только здесь. Если делать тяжёлые операции в UI Thread, приложение зависнет (ANR - Application Not Responding)!
val url = URL("https://example.com")
val connection = url.openConnection() as HttpURLConnection // Ошибка!


🚩`Worker Thread` – фоновый поток

- Выполняет долгие операции, не блокируя UI:
Запросы в сеть (Retrofit, OkHttp)
Чтение/запись в БД (Room, SQLite)
Обработку файлов, JSON, XML
Любые тяжёлые вычисления
CoroutineScope(Dispatchers.IO).launch {
val url = URL("https://example.com")
val connection = url.openConnection() as HttpURLConnection // Работает!
}


🚩Как переключаться между `UI Thread` и `Worker Thread`?
Способ 1: Coroutines (лучший вариант)
CoroutineScope(Dispatchers.IO).launch {
val data = fetchData() // Работает в `Worker Thread`

withContext(Dispatchers.Main) {
textView.text = data // Назад в `UI Thread`
}
}


Способ 2: Handler + Thread (старый вариант)
val handler = Handler(Looper.getMainLooper())

Thread {
val data = fetchData() // Работает в `Worker Thread`

handler.post {
textView.text = data // Назад в `UI Thread`
}
}.start()


Способ 3: AsyncTask (УСТАРЕЛ, НЕ ИСПОЛЬЗОВАТЬ!)
class MyTask : AsyncTask<Void, Void, String>() {
override fun doInBackground(vararg params: Void?): String {
return fetchData() // `Worker Thread`
}

override fun onPostExecute(result: String) {
textView.text = result // `UI Thread`
}
}


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

`Activity` в Android — это компонент приложения, который представляет один экран пользовательского интерфейса и отвечает за взаимодействие с пользователем. Каждое приложение может содержать несколько Activity, и они управляются системой Android в рамках жизненного цикла. Activity управляет пользовательским вводом, отображением данных и переходами между экранами. Это основной блок для создания интерактивных приложений на Android.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥2🤯2👀1
🤔 Как можно гарантировать быструю отрисовку чатов?

Чтобы чат работал быстро и без лагов, нужно:
Оптимизировать RecyclerView (ViewHolder, DiffUtil, Payloads).
Минимизировать работу в UI Thread (использовать Coroutines, Paging 3).
Оптимизировать загрузку изображений (Glide, Coil).
Использовать Room + Flow / LiveData для офлайн-кеша.

🚩Оптимизация `RecyclerView`

🟠Используем `ListAdapter` + `DiffUtil`
Вместо notifyDataSetChanged() лучше использовать ListAdapter, который сам обновляет только изменённые сообщения.
class ChatAdapter : ListAdapter<Message, ChatViewHolder>(DIFF_CALLBACK) {

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

override fun areContentsTheSame(oldItem: Message, newItem: Message): Boolean =
oldItem == newItem // data class сравнит автоматически
}
}
}


🟠Используем `Payloads` для частичного обновления
Если, например, только статус сообщения изменился, не нужно перерисовывать всё сообщение!
override fun getChangePayload(oldItem: Message, newItem: Message): Any? {
return if (oldItem.status != newItem.status) "STATUS_CHANGED" else null
}


Пример в onBindViewHolder()
override fun onBindViewHolder(holder: ChatViewHolder, position: Int, payloads: MutableList<Any>) {
if (payloads.contains("STATUS_CHANGED")) {
holder.updateStatus() // Обновляем только статус
} else {
super.onBindViewHolder(holder, position, payloads)
}
}


🚩Оптимизируем загрузку сообщений (Coroutines, Paging 3)

Запросы в БД в Worker Thread (Coroutines + Room)
fun loadMessages(): Flow<List<Message>> = messageDao.getMessages()


Используем Paging 3 для подгрузки сообщений
val pager = Pager(
config = PagingConfig(pageSize = 20),
pagingSourceFactory = { messageDao.getPagedMessages() }
).flow.cachedIn(viewModelScope)


🚩Загружаем изображения асинхронно (Glide, Coil)
Если чат содержит аватары или изображения, они должны загружаться лениво и в фоновом потоке.
Glide.with(context)
.load(user.avatarUrl)
.circleCrop()
.placeholder(R.drawable.placeholder)
.into(imageView)


🚩Используем Room для офлайн-кеша

Чтобы сообщения не загружались из сети при каждом запуске, сохраняем их в Room.
@Dao
interface MessageDao {
@Query("SELECT * FROM messages ORDER BY timestamp DESC")
fun getMessages(): Flow<List<Message>>

@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertMessages(messages: List<Message>)
}


🚩Оптимизируем `RecyclerView` для плавного скролла

Используем setHasFixedSize(true), если сообщения не меняют размер
recyclerView.setHasFixedSize(true)


Используем setItemViewCacheSize(), чтобы кэшировать ViewHolder
recyclerView.setItemViewCacheSize(20)


Отключаем анимации RecyclerView (если лагает)
(recyclerView.itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false


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

В Kotlin для многопоточности часто используются корутины, которые позволяют выполнять асинхронный код в синхронном стиле. Также можно использовать традиционные подходы, такие как потоки (Threads) и исполнители (Executors) из Java.

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

По умолчанию нельзя, потому что дженерики стираются (Type Erasure) во время компиляции.
fun <T> printType(value: T) {
println(T::class.simpleName) // Ошибка! Нельзя использовать `T::class`
}


🚩Как получить тип дженерика? (`reified`)

Если используем inline fun, можно сделать дженерик "реальным" (reified).
inline fun <reified T> printType(value: T) {
println(T::class.simpleName) // Работает!
}

fun main() {
printType(123) // Int
printType("Hello") // String
printType(3.14) // Double
}


🚩Как получить тип дженерика в классе? (`KType`)

Если дженерик используется в классе, то reified не поможет.
class MyGenericClass<T>(private val type: KClass<T>) {
fun printType() {
println(type.simpleName) // Работает
}
}

fun main() {
val obj = MyGenericClass(String::class)
obj.printType() // String
}


🚩Как получить тип списка (`List<T>`) в `runtime`?

Для сложных дженериков (List<T>, Map<K, V>) используем typeOf<T>() (только с reified).
import kotlin.reflect.typeOf

inline fun <reified T> printGenericType() {
val type = typeOf<T>()
println(type) // List<Int>, Map<String, Boolean> и т. д.
}

fun main() {
printGenericType<List<Int>>() // kotlin.collections.List<kotlin.Int>
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
🤔 Чем launch отличается от async/await

В Kotlin launch и async — это функции для запуска корутин, но они отличаются по назначению и возвращаемому значению. launch запускает корутину, но не возвращает результат, обычно используется для выполнения фоновой работы без ожидания результата, например, обновления UI. async, напротив, возвращает Deferred объект, который можно ожидать с помощью await, и предназначен для получения результата вычислений, что полезно для асинхронных операций с возвращаемым значением.

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

Софткод (Softcode, Soft Coding) — это подход к программированию, при котором логика программы хранится в конфигурационных файлах, базе данных или других внешних источниках, а не жёстко (hardcoded) прописана в коде.

🚩Разница между Hardcode и Softcode

Пример Hardcode (жёстко зашито в коде)
val apiUrl = "https://api.example.com" //  Если URL изменится, надо менять код


Пример Softcode (гибко через конфигурацию)
val apiUrl = Config.get("api_url") //  Загружается из настроек


🚩Где используется софткод?

Конфигурационные файлы (config.json, .properties, .xml).
База данных (логика, настройки, права пользователей).
API и сервер (получение UI-элементов, бизнес-логики с сервера).
Скриптовые языки (скрипты загружаются динамически).

🚩Примеры использования Softcode в Android

Softcode через SharedPreferences (конфигурация в памяти)
val sharedPrefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
val theme = sharedPrefs.getString("app_theme", "light") // Загружаем тему из настроек


Softcode через remoteConfig (Firebase Remote Config)
val minVersion = Firebase.remoteConfig.getInt("min_supported_version")


Softcode через JSON-файл (читаем конфиг из assets)
fun getConfigValue(context: Context, key: String): String {
val json = context.assets.open("config.json").bufferedReader().use { it.readText() }
val jsonObject = JSONObject(json)
return jsonObject.getString(key) // Получаем значение из JSON
}


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

Это область, в которой выполняются корутины в Kotlin. Определяет жизненный цикл корутин и позволяет отменять их при завершении scope.
- GlobalScope – живет все время работы приложения, но редко используется.
- viewModelScope – в ViewModel, отменяется при уничтожении ViewModel.
- lifecycleScope – в Activity/Fragment, отменяется при уничтожении UI.


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

Библиотека Lifecycle в Android Jetpack помогает управлять и контролировать жизненный цикл компонентов Android, таких как Activities и Fragments. Она упрощает создание компонентов, которые осведомлены о своем жизненном цикле и могут корректно реагировать на изменения в нем. Это позволяет избегать утечек памяти и некорректной работы компонентов при изменении конфигураций или переходах между состояниями.

🚩Основные компоненты библиотеки Lifecycle

🟠LifecycleOwner
Это интерфейс, который определяет класс как владеющий жизненным циклом. Activity и Fragment уже реализуют этот интерфейс.
class MyActivity : AppCompatActivity(), LifecycleOwner {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}


🟠LifecycleObserver
Это интерфейс, который позволяет классу наблюдать за изменениями в жизненном цикле компонента. Методы, аннотированные @OnLifecycleEvent, будут вызываться при соответствующих событиях жизненного цикла.
class MyObserver : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onStart() {
// Код, который выполняется при старте жизненного цикла
Log.d("MyObserver", "onStart called")
}

@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun onStop() {
// Код, который выполняется при остановке жизненного цикла
Log.d("MyObserver", "onStop called")
}
}


🟠Lifecycle
Это класс, который содержит информацию о текущем состоянии и позволяет другим объектам наблюдать за изменениями в жизненном цикле.
class MyActivity : AppCompatActivity() {
private lateinit var myObserver: MyObserver

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

myObserver = MyObserver()
lifecycle.addObserver(myObserver)
}
}


🚩Применение библиотеки Lifecycle

1⃣ Добавьте зависимости в ваш build.gradle
dependencies {
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
}


2⃣Создайте класс, реализующий LifecycleObserver
class MyObserver : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun onResume() {
Log.d("MyObserver", "Activity resumed")
}

@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun onPause() {
Log.d("MyObserver", "Activity paused")
}
}


3⃣Добавьте LifecycleObserver в LifecycleOwner (например, Activity)
class MyActivity : AppCompatActivity() {
private lateinit var myObserver: MyObserver

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

myObserver = MyObserver()
lifecycle.addObserver(myObserver)
}
}


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

1. synchronized блоки в Java/Kotlin работают на уровне потоков, а не корутин – это разные механизмы синхронизации.
2. Блокировка потоков замедляет работу – Mutex работает в асинхронном стиле, не блокируя потоки.
3. Глобальные synchronized блоки не учитывают отмену корутин – если корутина отменена, synchronized не освобождает ресурс.


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

Чтобы добавить кастомные атрибуты в Custom View, нужно:
Создать attrs.xml и описать атрибуты.
Добавить их в styleable и получить в Custom View.
Использовать атрибуты в XML или Kotlin.

🟠Создаём `attrs.xml`
Создаём файл res/values/attrs.xml, если его нет:
<resources>
<declare-styleable name="CustomButton">
<attr name="customText" format="string"/>
<attr name="customTextSize" format="dimension"/>
<attr name="customTextColor" format="color"/>
</declare-styleable>
</resources>


🟠Создаём `Custom View` и получаем атрибуты
Теперь создаём CustomButton.kt
class CustomButton @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : AppCompatButton(context, attrs, defStyleAttr) {

init {
context.theme.obtainStyledAttributes(attrs, R.styleable.CustomButton, 0, 0).apply {
try {
val text = getString(R.styleable.CustomButton_customText) ?: "Default"
val textSize = getDimension(R.styleable.CustomButton_customTextSize, 16f)
val textColor = getColor(R.styleable.CustomButton_customTextColor, Color.BLACK)

setText(text)
setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize)
setTextColor(textColor)
} finally {
recycle() // Освобождаем ресурсы
}
}
}
}


🟠Используем `Custom View` в XML
Теперь можно использовать CustomButton в activity_main.xml
<com.example.customviews.CustomButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:customText="Нажми меня"
app:customTextSize="20sp"
app:customTextColor="@android:color/holo_red_dark"/>


🟠Как изменить атрибуты в коде?
Можно обновлять свойства прямо в Kotlin
val button = findViewById<CustomButton>(R.id.customButton)
button.text = "Новый текст"
button.setTextSize(TypedValue.COMPLEX_UNIT_SP, 24f)
button.setTextColor(Color.BLUE)


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

1. Начать с небольших компонентов: добавить Compose для отдельных виджетов, используя ComposeView внутри существующих XML-макетов.
2. Постепенно внедрять Compose для новых экранов или функций, сохраняя старые части на XML.
3. Разделить проект на модули, чтобы переключение между Compose и View не влияло на весь код.
4. Проводить тщательное тестирование и устранять баги на каждом этапе интеграции.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥2🤯2😁1
🤔 Опиши как лучше всего использовать модиффВ каком порядке вызываеться конструктор, конструктор супер класса, статический инит блок икаторы доступа в Java?

Конструктор (constructor)
Конструктор суперкласса (super)
Статический блок инициализации (static {})
Обычный блок инициализации ({})

🚩Общий порядок вызова

При создании объекта в Java выполняются шаги:
Статические блоки суперкласса (static {} в родителе)
Статические блоки текущего класса (static {})
Обычные блоки инициализации суперкласса ({} в родителе)
Конструктор суперкласса (super(...))
Обычные блоки инициализации текущего класса ({})
Конструктор текущего класса
class Parent {
static { System.out.println("1️⃣ Статический блок Parent"); }
{ System.out.println("3️⃣ Обычный блок Parent"); }

Parent() {
System.out.println("4️⃣ Конструктор Parent");
}
}

class Child extends Parent {
static { System.out.println("2️⃣ Статический блок Child"); }
{ System.out.println("5️⃣ Обычный блок Child"); }

Child() {
System.out.println("6️⃣ Конструктор Child");
}
}

public class Main {
public static void main(String[] args) {
System.out.println("🔹 Создаём объект Child");
new Child();
}
}


Вывод в консоль
Статический блок Parent
Статический блок Child
Создаём объект Child
Обычный блок Parent
Конструктор Parent
Обычный блок Child
Конструктор Child


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Forwarded from easyoffer
Я боялся, что провалю собеседование. Так появился easyoffer

Когда я только начинал искать первую работу программистом, меня пугала мысль, что я просто не смогу ответить на вопросы на собеседовании.

Типа… ты потратил месяцы на то, чтобы учиться, писал pet-проекты, собирал резюме, рассылаешь отклики — и всё может закончиться на одном-единственном вопросе, на который ты не знаешь ответ.

Я реально боялся.
Я смотрел видео mock-собеседований на YouTube, останавливал каждое, выписывал вопросы в Notion. Потом вручную писал к ним ответы. И потом ещё по нескольку раз перечитывал. Такой вот "тренажёр" на коленке.

📎 (там на картинке — один из моих реальных списков в Notion, ставь 🔥 если тоже так делал)

В какой-то момент я посчитал — у меня уже было выписано больше 500 вопросов. Я почувствовал ужас.
Потому что невозможно всё это зазубрить. А что, если спросят как раз тот, к которому я не успел подготовиться?..

Тогда и пришла идея

А что если понять, какие из вопросов встречаются чаще всего? Чтобы не учить всё подряд, а сфокусироваться на главном.

Так родился easyoffer.

Сначала — просто как пет-проект, чтобы показать в резюме и подготовиться к собесам. А потом оказалось, что он реально помогает людям. За первые месяцы его посетили сотни тысяч человек. И я понял: это больше, чем просто пет-проект.

Сейчас я делаю EasyOffer 2.0
И уже не один, а вместе с вами.

В новой версии будут:
– вопросы из реальных собесов, с фильтрацией по грейду, компании, типу интервью
– тренажёр с карточками (по принципу интервальных повторений — как в Anki)
– база задач с интервью
– тренажёр «реальное собеседование», чтобы отрепетировать как в жизни

Каждая фича упрощает и сокращает время на подготовку. Все эти штуки я бы мечтал иметь, когда сам готовился к собеседованиям.

Я делаю всё на свои деньги. Никаких инвесторов. Только вы и я.

Если вы хотите помочь — сейчас самое важное время.
Краудфандинг уже стартовал. Благодаря нему я смогу привлечь больше людей для разработки, сбору и обработки собеседований.

Все, кто поддержат проект до релиза, получат:

🚀 1 год PRO-доступа по цене месячной подписки. Его можно активировать в любое время, например когда начнете готовится к собесам.
Доступ к закрытому бета-тесту

Поддержать 👉 https://planeta.ru/campaigns/easyoffer

Спасибо, что верите в этот проект 🙌
👍2🔥1