JuniorJava Developer > Java Core > ООП
Короткий ответ Наследование — механизм ООП, при котором подкласс (наследник) создаётся на основе другого класса — суперкласса (родителя) — через ключевое слово extends и получает доступ к его не-private членам. Наследник может добавлять свои члены и переопределять унаследованные методы. В Java у класса может быть только один непосредственный родитель. Как это работает подробнее Отношение между наследником и родителем описывается как «является» (IS-A): Cat — это Animal. Наследование уменьшает дублирование кода и служит фундаментом полиморфизма. Переиспользование кода. Общие поля и методы выносятся в базовый класс, и каждый наследник не дублирует их, а просто наследует. IS-A и полиморфизм. Там, где ожидается Animal, можно передать Cat: ссылка родительского типа указывает на объект наследника, и вызывается реализация метода именно наследника. Конструкторы не наследуются. Наследник обязан вызвать конструктор родителя через super(); компилятор добавляет такой вызов автоматически, если у родителя есть конструктор б
extendsinheritance
MiddleJava Developer > Java Core > JVM и память
Короткий ответ Стек создаётся для каждого потока отдельно и хранит кадры методов: локальные переменные, параметры и служебную информацию; работает по принципу LIFO. Куча — общая для всех потоков область, в которой размещаются объекты и массивы, созданные через new. Локальные переменные-примитивы хранятся в стеке; если примитив — поле объекта, он лежит в куче вместе с объектом. Как это работает подробнее При вызове метода в стеке выделяется кадр, при возврате из метода он разрушается. Стек живёт недолго и имеет фиксированный, обычно небольшой размер; его переполнение приводит к StackOverflowError. Куча обычно значительно больше стека, её размер задаётся параметрами -Xmx и -Xms. Объект в куче живёт, пока на него есть ссылки, а освобождением памяти занимается сборщик мусора. Для работы GC куча делится на поколения: молодое (Eden и survivor-области) и старое. Если ссылка на объект — локальная переменная, сама ссылка лежит в стеке потока, а объект — в куче. В памяти JVM есть и другие области: Metaspace (метаданные
heapjava
MiddleJava Developer > Java Core > JPA и Hibernate
Короткий ответ Кэширование в Hibernate хранит часто запрашиваемые данные в памяти, уменьшая обращения к базе. Кэш первого уровня (First-Level Cache, Session Cache) включён по умолчанию и привязан к конкретной Session: повторно запрошенный в той же сессии объект возвращается из памяти без запроса к БД. Кэш второго уровня (Second-Level Cache, SessionFactory Cache) — общий для всех сессий фабрики; по умолчанию выключен и требует явной настройки. Как это работает подробнее Разница — в границе действия. Первый уровень живёт в пределах одной Session: он обеспечивает согласованность данных на уровне транзакции, но недоступен другим сессиям. Второй уровень действует на уровне всего приложения, поддерживает параллельный доступ нескольких сессий и может хранить данные не только в памяти, но и во внешнем хранилище. Первый уровень: всегда включён, не настраивается, хранится в памяти сессии. Второй уровень: опционален и конфигурируем: подключается провайдер кэша (например, Ehcache или Redis), включается свойство hibernate
cachingfirst-level-cache
SeniorJava Developer > Java Core > Сборка мусора
Короткий ответ Разница между ссылками — в моменте, когда GC может удалить объект. SoftReference удерживает объект, пока JVM не столкнётся с нехваткой памяти: сборщик удаляет soft-доступные объекты обычно перед OutOfMemoryError. WeakReference ещё слабее: объект, доступный только по слабой ссылке, может быть удалён уже при ближайшей сборке, как только исчезнут сильные ссылки на него. Как это работает подробнее Мягкие ссылки удобны для кэшей, где данные можно пересоздать: они живут максимально долго, но не приводят к переполнению памяти. Слабые ссылки подходят для вспомогательных данных, потерю которых можно пережить; классический пример — WeakHashMap, где записи исчезают, когда их ключи больше не используются сильными ссылками. PhantomReference — крайний случай: объект, доступный только по фантомной ссылке, фактически уже недоступен, метод get() всегда возвращает null. Фантомные ссылки применяются с ReferenceQueue, чтобы выполнить действия «перед удалением» объекта или надёжно отследить, что объект действительн
gcjava
MiddlePython Developer > Основы Python > Исключения и контекстные менеджеры
Короткий ответ Голый except перехватывает абсолютно все исключения, включая KeyboardInterrupt, SystemExit и GeneratorExit, тогда как except Exception их не трогает. На практике ловят конкретные ожидаемые типы: код реагирует на разные ошибки по-разному, а посторонние сбои не маскируются. Как это работает подробнее Разница определяется иерархией исключений и тем, насколько широкий круг ошибок попадает в обработчик. Иерархия исключений. От BaseException наследуются и Exception, и системные KeyboardInterrupt, SystemExit, GeneratorExit, поэтому except Exception их не перехватывает. Голый except. Не сообщает, какая ошибка произошла: реальный тип скрыт, программа «проглатывает» баг, а пользователь не может прервать её по Ctrl+C. Порядок обработчиков. Их располагают от конкретных к общим, иначе первый общий обработчик перехватит ошибку раньше и остальные не сработают. Допустимый случай. Голый except оправдан лишь как страховочная сетка в самом конце цепочки и при полном понимании рисков. Пример кода Что использовать
error-handlingexcept
MiddlePython Developer > Основы Python > Многопоточность и асинхронность
Короткий ответ Процесс — независимая единица выполнения с собственным адресным пространством и своим интерпретатором Python. Поток — лёгкая единица внутри процесса: все потоки разделяют его память и данные. Как это работает подробнее Главные отличия лежат в модели памяти, стоимости создания и способности к параллельному исполнению. Память. Процессы изолированы и общаются через очереди, каналы и разделяемую память, а потоки напрямую читают и меняют общие объекты. Параллелизм. У каждого процесса свой GIL, поэтому они действительно выполняются на нескольких ядрах; потоки одного процесса для вычислений ограничены GIL. Стоимость. Процессы тяжелее: их создание и переключение дороже, а потоки создаются дёшево и быстро обмениваются данными. Синхронизация. Из-за общей памяти в потоках нужны блокировки против гонок данных, процессы в такой защите не нуждаются. Что использовать на практике Процессы. Бери, когда нужны изоляция и настоящий параллелизм для вычислительных задач. Потоки. Бери для лёгких задач с интенсивным о
concurrencymultiprocessing
JuniorJava Developer > Java Core > Collections
Короткий ответ Исторический класс Vector (Java 1.0) делает все свои методы synchronized, то есть каждый вызов защищён монитором на уровне объекта; ArrayList появился позже (Java 2) и не синхронизирован, поэтому в однопоточном коде работает заметно быстрее. Vector при переполнении удваивает размер массива (или растёт на capacityIncrement), а ArrayList увеличивает ёмкость примерно в полтора раза: oldCapacity + (oldCapacity >> 1). Как это работает подробнее Оба класса реализуют интерфейс List и внутри используют обычный массив, поэтому логика работы похожа. Разница в производительности — следствие синхронизации: у Vector она глобальная и приходится на каждый вызов, у ArrayList её нет вовсе. Из-за этого Vector считается устаревшим (legacy), хотя и не удалён из стандартной библиотеки. Потокобезопасность: Vector синхронизирован, но такая «безопасность» покупается блокировкой на каждой операции. Современная замена: при необходимости синхронизации берут ArrayList с Collections.synchronizedList(...) либо потокобезопас
arraylistcollections
MiddleJava Developer > Java Core > Multithreading
Короткий ответ Процесс — это программа в состоянии выполнения с собственным изолированным адресным пространством памяти. Поток — «лёгковесная» единица выполнения внутри процесса; в Java сам процесс — это запущенная JVM, внутри которой работают десятки потоков: main, потоки сборщика мусора, пользовательские потоки. Как это работает подробнее Потоки одного процесса разделяют кучу и другие общие области памяти, поэтому могут общаться через общие объекты и переменные, но при этом каждый имеет собственный стек вызовов и программный счётчик — локальные переменные у потоков не общие. Из-за разделяемой памяти и возникает риск гонок за данные. Процессы полностью изолированы: крах одного процесса не «роняет» другой, однако обмен данными между ними требует специальных механизмов — сокетов, файлов, разделяемой памяти. Создание и переключение потоков обходятся заметно дешевле, чем у процессов, поэтому многопоточность эффективнее использует ресурсы системы и многоядерные процессоры. Пример кода Что использовать на практике
javamemory
MiddlePython Developer > Основы Python > Алгоритмы и типовые задачи
Короткий ответ Хороший код следует PEP 8, читаем, разбит на небольшие функции с ясными именами, лишён дублирования и магических чисел, обрабатывает краевые случаи и покрыт тестами. Плохой код нечитаем и трудно поддерживать. Алгоритмическую задачу решают по методике: понять условие, оценить сложность, написать рабочее решение, затем оптимизировать и протестировать. Как это работает подробнее Разница между хорошим и плохим кодом видна в читаемости, структуре и тестах, а надёжная методика решения задач помогает не начинать писать код наугад. PEP 8. Свод рекомендаций по оформлению кода: отступы, именование, длина строк; следование ему делает код единообразным и лёгким для чтения коллегами. Структура кода. Хороший код решает задачу просто, разбит на небольшие функции с понятными именами, лишён дублирования и обрабатывает краевые случаи. Тесты и сопровождение. Покрытие тестами — признак зрелого кода; плохой код нечитаем, полон магических чисел и скрытых побочных эффектов, поэтому его страшно менять. Понимание задач
code-qualitypep8
JuniorPython Developer > Основы Python > Основы Python
Короткий ответ F-строки (f-strings) — форматированные строковые литералы, появившиеся в Python 3.6: перед строкой ставится буква f, а переменные и выражения подставляются прямо внутри фигурных скобок. Они лаконичнее метода .format(), читаются лучше и обычно работают быстрее. Как это работает подробнее Преимущества f-строк связаны с синтаксисом, читаемостью и производительностью. Встраивание выражений. F-строка подставляет переменные и выражения прямо в литерал, тогда как в .format() имена приходится дублировать в аргументах. Любые выражения. Внутри фигурных скобок допустимо любое валидное выражение Python, например f'{price * (1 + tax_rate):.2f}' — цена вычисляется прямо в строке и сразу форматируется с двумя знаками после запятой. Скорость. Значения вычисляются при разборе строкового литерала, а не через вызов отдельного метода, поэтому f-строки, как правило, быстрее .format(). Наследие. Метод .format() и оператор % всё ещё встречаются в старых проектах, поэтому их нужно уметь читать. Пример кода Что использ
f-stringsformat