Skip to content

Latest commit

 

History

History
218 lines (174 loc) · 38.7 KB

File metadata and controls

218 lines (174 loc) · 38.7 KB

Java

База

  • Стек (Stack) и куча (Heap)

  1. Стек работает по схеме LIFO (последним вошел, первым вышел). Всякий раз, когда вызывается новый метод, содержащий примитивные значения или ссылки на объекты, то на вершине стека под них выделяется блок памяти. Из этого можно сделать вывод, что стек хранит значения примитивных переменных, создаваемых в методах, а также ссылки на объекты в куче на которые ссылается метод.
    Когда метод завершает выполнение, блок памяти (frame), отведенный для его нужд, очищается, и пространство становится доступным для следующего метода. При этом поток выполнения программы возвращается к месту вызова этого метода с последующим переходом к следующей строке кода.
  2. Куча. Эта область памяти используется для динамического выделения памяти для объектов и классов JRE во время выполнения. Новые объекты всегда создаются в куче, а ссылки на них хранятся в стеке.
    Эти объекты имеют глобальный доступ и могут быть получены из любого места программы.
    • Young Generation — область где размещаются недавно созданные объекты. Когда она заполняется, происходит быстрая сборка мусора
    • Old (Tenured) Generation — здесь хранятся долгоживущие объекты. Когда объекты из Young Generation достигают определенного порога «возраста», они перемещаются в Old Generation
    • Permanent Generation — эта область содержит метаинформацию о классах и методах приложения, но начиная с Java 8 данная область памяти была упразднена.
  • JDK, JRE, JVM, JIT

    • JDK (Java Development Kit) - это полный пакет для разработчиков Java, который включает в себя JRE (Java Runtime Environment) и компилятор Java (javac), а также другие инструменты, необходимые для разработки Java-приложений, такие как документирование (javadoc) и инструмент для архивации (jar). JDK позволяет разрабатывать и тестировать Java-приложения.
    • JRE (Java Runtime Environment) - это часть программного обеспечения, которая используется для запуска Java-приложений. Она включает в себя JVM (Java Virtual Machine), библиотеки классов и другие файлы, необходимые для выполнения программ, написанных на языке Java. JRE необходима для запуска, но не для разработки Java-приложений.
    • JVM (Java Virtual Machine) - это виртуальная машина, которая исполняет байт-код Java. Она отвечает за загрузку кода, проверку кода на безопасность, его выполнение и предоставление среды выполнения, которая изолирует приложение от операционной системы. JVM делает Java платформо-независимым языком, так как байт-код может выполняться на любой машине, на которой установлена JVM.
    • JIT (Just-In-Time Compiler) - это компонент JVM, который увеличивает скорость выполнения Java-приложений, компилируя байт-код в родной машинный код во время выполнения программы. Вместо интерпретации байт-кода на лету, JIT компилирует часто выполняемые части кода в машинный код для увеличения производительности.

JDK

  • ClassLoader

    ClassLoader - это часть JVM, которая загружает классы Java во время выполнения. ClassLoader загружает байт-код из файлов классов (.class) в Java Runtime Environment. Он играет важную роль в концепции безопасности Java, так как разделяет пространство имен классов в соответствии с их источниками (например, классы из локальной файловой системы и классы из сетевых источников).

ООП

  • Объясните концепты ООП в Java.

    ООП (Объектно-Ориентированное Программирование) в Java включает в себя четыре основных концепта:

    • Инкапсуляция: Сокрытие внутренней реализации класса и защита его данных.
    • Наследование: Создание новых классов на основе существующих.
    • Полиморфизм: Один и тот же метод может работать по-разному в зависимости от объекта, где он вызван, и данных, которые ему передали.
    • Абстракция: это когда мы сосредотачиваемся только на существенных для задачи деталях и игнорируем всё остальное. В ООП абстракция означает, что для каждого объекта мы задаём минимальное количество методов, полей и описаний, которые позволят нам решить задачу. Чем меньше характеристик, тем лучше абстракция, но ключевые характеристики убирать нельзя.
  • Различия между абстрактными классами и интерфейсами?

    • Абстрактный класс - это класс, который содержит как конкретные, так и абстрактные методы (методы без реализации). Абстрактный метод должен быть реализован подклассами абстрактного класса. Абстрактные классы не могут быть инстанцированы и должны быть расширены для использования. Наследовать можно только 1 абстрактный класс.
    • Интерфейс подобен чертежу/контракту класса (или его можно рассматривать как класс с методами, но без их реализации). Он содержит пустые методы, которые представляют, что должно быть общим у всех его подклассов. Подклассы обеспечивают реализацию каждого из этих методов. Интерфейсы реализуются. Наследовать можно сколько угодно интерфейсов.
  • Разница между перегрузкой метода и переопределением метода.

    • Перегрузка метода (Method Overloading): Это когда несколько методов в одном классе имеют одно и то же имя, но различаются по типу и/или количеству параметров.
    • Переопределение метода (Method Overriding): Это когда подкласс заменяет метод своего суперкласса.
  • Какие модификаторы доступа вы знаете? Что делает каждый из них?

    В Java существует четыре модификатора доступа (от строжайшего к наиболее либеральному):

    • private переменные, методы, конструкторы или внутренние классы видны только внутри своего класса и его методов. Этот модификатор чаще всего используется, например, для доступа к переменным только через геттеры и сеттеры или для скрытия внутренней реализации классов, которые не должны использоваться пользователем, тем самым поддерживая инкапсуляцию. Конструктор Singleton также помечается как private, чтобы избежать нежелательного инстанцирования извне.
    • Default (ключевое слово не используется) этот модификатор может быть применен к классам, переменным, конструкторам и методам и позволяет доступ из классов и методов внутри того же пакета.
    • protected может использоваться для переменных, методов и конструкторов, тем самым разрешая доступ только подклассам и классам внутри того же пакета, что и класс защищенных членов.
    • public модификатор широко используется для классов, переменных, конструкторов и методов для предоставления доступа из любого класса и метода где угодно. Его не следует использовать повсеместно, поскольку это подразумевает, что данные, помеченные как public, не являются чувствительными и не могут быть использованы для нанесения вреда программе.
  • Может ли интерфейс реализовать другой интерфейс?

    Да, интерфейс может реализовать другой интерфейс (и более одного), но ему нужно использовать ключевое слово extends, а не implements. И хотя вы не можете удалять методы из родительского интерфейса, вы можете свободно добавлять новые к своему подинтерфейсу.

  • Что такое Полиморфизм? Что такое Наследование?

    • Полиморфизм: Это способность одного и того же кода вести себя по-разному в зависимости от контекста, в основном достигается через переопределение метода.
    • Наследование: Это механизм в Java, позволяющий одному классу использовать поля и методы другого класса.

Коллекции и дженерики

  • Arrays против ArrayLists

    • Arrays: Простые, фиксированной длины структуры данных для хранения элементов одного типа.
    • ArrayLists: Реализация изменяемого массива в Java, которая может автоматически увеличиваться и уменьшаться.
  • ArrayList vs LinkedList

    ArrayList это динамический массив, оптимизированный для быстрого доступа к элементам, а LinkedList — как список со связями между элементами, оптимизированный для операций вставки и удаления. Сценарии использования: если вам часто нужен доступ к элементам по индексу, выбирайте ArrayList; если в приоритете вставка и удаление, то LinkedList.

  • Расскажите как работает HashMap

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

  • HashSet против TreeSet

    • HashSet: Реализация множества, использующая хеш-таблицу для хранения элементов. Не гарантирует порядка элементов.
    • TreeSet: Реализация множества, основанная на красно-черном дереве, которая поддерживает упорядоченность элементов по возрастанию.
  • HashMap против Set

    • HashMap: Коллекция, использующая пары ключ-значение для хранения данных, где каждый ключ уникален.
    • Set: Интерфейс, представляющий коллекцию уникальных элементов, не допускающий дублирования.
  • Объясните дженерики в Java.

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

Объекты и примитивы

  • Как реализован класс String? Почему он был сделан неизменяемым?

    В Java нет примитивного варианта класса String - все строки являются просто обертками вокруг базового массива символов, который объявлен как final. Это означает, что, как только объект String создан, он не может быть изменен с помощью обычных инструментов языка (Reflection все еще может ужасно все испортить, потому что в Java никакой объект на самом деле не является полностью неизменяемым). Именно поэтому переменные класса String являются первыми кандидатами для использования, когда вы хотите переопределить hashCode() и equals() вашего класса - вы можете быть уверены, что все их требуемые контракты будут выполнены.

  • Что значит сказать, что строка (String) неизменяема?

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

  • Что такое класс Object?

    Это корневой класс в иерархии классов Java. Все классы наследуются от Object. Ключевые методы класса Object включают equals(), hashCode(), toString(), getClass(), clone(), notify(), notifyAll(), и wait().

  • Что такое хэш-код?

    В Java хэш-код объекта — это целое число, используемое для распределения объектов в хэш-таблице. Если метод hashCode() не переопределен, класс Object предоставляет реализацию, которая преобразует внутренний адрес объекта в целое число.

  • Можете ли вы перечислить 8 примитивных типов в Java?

    • byte
    • short
    • int
    • long
    • float
    • double
    • char
    • boolean
  • В чем разница между примитивами?

    • Числовые типы: byte (8 бит), short (16 бит), int (32 бита), long (64 бита) представляют целочисленные значения разного размера. float (32 бита) и double (64 бита) представляют числа с плавающей точкой.
    • Логический тип: boolean представляет значения истина/ложь.
    • Символьный тип: char (16 бит) представляет символы в Unicode.
  • В чем разница между Integer и int?

    • int: примитивный тип данных, представляющий целочисленные значения.
    • Integer: класс-обертка, предоставляющий методы для работы с объектами, содержащими целочисленные значения, и позволяющий использовать int в качестве объектов.
  • Передаются ли объекты по ссылке или по значению в Java? Раскройте этот вопрос.

    В Java все параметры передаются по значению. Для объектов значение ссылки на объект копируется в параметр метода.

  • Что происходит, когда объект больше не нужен?

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

  • Что такое сборщик мусора? Как он работает?

    https://javarush.com/quests/lectures/questservlets.level18.lecture03
    Сборщик мусора в Java автоматически удаляет объекты, на которые больше нет ссылок, тем самым освобождая память для повторного использования. Все объекты размещаются в куче, управляемой JVM. Пока на объект ссылаются, JVM считает его живым. Как только на объект больше не ссылаются и, следовательно, он недоступен для кода приложения, сборщик мусора удаляет его и освобождает неиспользуемую память.
    В контексте GC важно понятие "графа достижимости" (reachability graph). В этом графе объекты представляются узлами, а ссылки между объектами — рёбрами. Корни этого графа — это набор "живых" объектов, доступных напрямую (например, локальные переменные стека, активные потоки выполнения, статические поля классов и т.п.). Объект считается "живым" и не подлежит удалению GC, если он достижим, то есть до него можно добраться по цепочке ссылок от одного из корней.

  • Типы ссылок в Java

    • Strong Reference (Сильная ссылка): Обычная ссылка, предотвращающая сбор мусора для объекта, пока существует сильная ссылка.
    • Soft Reference (Мягкая ссылка): Сбор мусора для таких объектов происходит только в случае нехватки памяти.
    • Weak Reference (Слабая ссылка): Объект может быть собран мусором при следующей сборке мусора, даже если есть слабые ссылки.
    • Phantom Reference (Фантомная ссылка): Объект, на который есть только фантомные ссылки, будет собран мусором, но перед этим будет помещен в очередь ссылок, что позволяет системе очистить его ресурсы.
  • Что такое переполнение памяти при выполнении программы и что происходит при переполнении памяти?

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

  • Что такое gc roots?

    В контексте сборки мусора (GC) в Java, GC Roots (корни сборки мусора) представляют собой набор объектов, которые являются отправной точкой для сборщика мусора при его работе. Эти объекты считаются "живыми" и не могут быть собраны сборщиком мусора. Сборщик мусора использует корни GC как начальные точки для определения доступных (достижимых) объектов. Любой объект, который можно достичь, пройдя от корней GC через цепочку ссылок, также считается живым и, следовательно, не подлежит уничтожению.
    GC Roots включают в себя:

    • Локальные переменные: Переменные, находящиеся в стеке вызовов (то есть переменные, принадлежащие активным методам).

    • Активные потоки: Объекты потока, которые все еще выполняются.

    • Статические поля: Переменные класса, поскольку они принадлежат классу, который находится в области PermGen (до Java 8) или Metaspace (начиная с Java 8) и доступен из любой точки приложения.

    • JNI (Java Native Interface) ссылки: Объекты, на которые ссылаются из нативного кода.

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

Многопоточность

  • Что такое deadlock и livelock?

    • Deadlock возникает, когда два или более потоков в системе ожидают ресурсов, занятых друг другом, в результате чего они вечно ждут и не могут продолжить выполнение.
    • Livelock – это ситуация, аналогичная deadlock, но потоки не заблокированы; они активно пытаются разрешить вопрос, но так и не достигают прогресса, постоянно меняя своё состояние в ответ на состояние друг друга.
  • Что такое race condition (гонка потоков)?

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

  • Что означает ключевое слово synchronized?

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

  • Что такое atomic classes и благодаря чему они являются атомарными?

    Классы из пакета java.util.concurrent.atomic, которые поддерживают атомарные операции на одном значении без использования синхронизации. Благодаря использованию низкоуровневых атомарных инструкций процессора, такие операции могут быть выполнены без блокировок, что делает их очень быстрыми и эффективными.

  • Что такое ThreadPoolExecutor?

    ThreadPoolExecutor - это реализация пула потоков в Java, которая управляет пулом рабочих потоков, позволяя эффективно выполнять множество асинхронных задач.

  • Что такое модификатор volatile?

    Указывает компилятору и виртуальной машине Java, что значение переменной может изменяться разными потоками. Это обеспечивает, что значение переменной будет считываться из основной памяти, а не из кэша CPU, гарантируя, что чтение переменной всегда дает последнее записанное значение.

  • Классы в пакете atomic предоставляют общий набор методов: get, set, lazyset, compareAndSet, и weakCompareAndSet.

    • get: возвращает текущее значение.
    • set: устанавливает новое значение.
    • lazyset: устанавливает новое значение с гарантией порядка изменений только в однопоточных контекстах.
    • compareAndSet: атомарно устанавливает новое значение, если текущее значение соответствует ожидаемому.
    • weakCompareAndSet: вариант compareAndSet с возможностью неудачи в некоторых ситуациях для улучшения производительности.

Исключения

  • Как работают try{}, catch{}, finally{}?

    • try{}: блок кода, в котором могут возникнуть исключения.
    • catch{}: блок кода, обрабатывающий исключение, возникшее в блоке try.
    • finally{}: блок кода, который выполняется после блоков try/catch, независимо от того, возникло исключение или нет.
  • В чем разница между Проверяемым Исключением и Непроверяемым Исключением?

    • Проверяемые исключения (Checked Exceptions): это исключения, которые должны быть явно перехвачены или объявлены в методе.
    • Непроверяемые исключения (Unchecked Exceptions): это исключения, которые не требуют явного перехвата или объявления в методе.

Другое

  • Что такое сериализация? Как вы ее реализуете?

    Сериализация - это процесс преобразования объекта в последовательность битов для сохранения или передачи. В Java это можно реализовать с помощью интерфейса Serializable.

  • Что такое модификатор transient?

    Модификатор transient используется для исключения полей класса при сериализации.

  • Что такое анонимные классы?

    Анонимные классы - это классы без имени, объявленные и инициализированные одновременно, обычно используются для создания экземпляров простых интерфейсов или классов на месте.

  • В чем разница между использованием == и .equals на объекте?

    • ==: проверяет равенство ссылок на объекты.
    • .equals(): проверяет равенство содержимого объектов.
  • Для чего используются hashCode() и equals()?

    Методы hashCode() и equals() используются для сравнения объектов. hashCode() возвращает хеш-код объекта, а equals() проверяет, равны ли два объекта.

  • Когда бы вы придали объекту значение final?

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

  • Что такое ключевые слова final, finally и finalize?

    • final: используется для объявления констант, методов, которые не могут быть переопределены, и классов, которые не могут быть наследованы.
    • finally: блок кода, который выполняется после блока try/catch в конструкции обработки исключений, независимо от того, было ли исключение.
    • finalize(): метод, вызываемый перед утилизацией объекта сборщиком мусора.
  • В чем разница между ключевыми словами "throw" и "throws" в Java?

    • throw: используется для явного выброса исключения.
    • throws: указывает на то, что метод может выбросить исключение, и требует его обработки или дальнейшего объявления.
  • Что означает слово static в Java?

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

  • Можно ли переопределить статический метод в Java?

    Статические методы не могут быть переопределены в том смысле, как переопределяются обычные методы. Они могут быть "скрыты" в подклассе, если в подклассе объявлен статический метод с тем же именем.

  • Когда выполняется статический блок?

    Статический блок выполняется при первой загрузке класса в JVM.

  • Что такое рефлексия?

    Рефлексия в Java позволяет программе исследовать или "размышлять" о себе самой, изменять свое поведение во время выполнения.

  • Что такое Внедрение Зависимостей (DI)?

    Внедрение зависимостей - это дизайн-паттерн, который позволяет классам получать свои зависимости извне, вместо их создания внутри себя, улучшая модульность и тестируемость.

  • Разница между StringBuffer и StringBuilder?

    • StringBuffer: потокобезопасная версия изменяемой последовательности символов.
    • StringBuilder: не потокобезопасная версия, более быстрая по сравнению с StringBuffer при выполнении операций в однопоточном режиме.
  • В чем разница между быстро-сбойными и безопасно-сбойными итераторами в Java?

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

  • Монитор и Синхронизация

    Монитор в Java - это механизм, обеспечивающий возможность синхронизированного доступа к блоку кода или методу, так что в каждый момент времени только один поток может исполнять блок кода или метод, помеченный как synchronized. Синхронизация используется для предотвращения проблем совместного доступа и состояния гонки, обеспечивая, чтобы только один поток мог выполнить определенный участок кода, работающий с общими ресурсами, в данный момент времени.