Java Core - 1 Flashcards

1
Q
  1. Что такое ООП?
A

Объектно-ориентированное программирование (ООП) — методология программирования, основанная на представлении программы в виде совокупности объектов, каждый из которых является экземпляром определенного класса, а классы образуют иерархию наследования.
● объектно-ориентированное программирование использует в качестве основных логических
конструктивных элементов объекты, а не алгоритмы;
● каждый объект является экземпляром определенного класса
● классы образуют иерархии.
Согласно парадигме ООП программа состоит из объектов, обменивающихся сообщениями.
Объекты могут обладать состоянием, единственный способ изменить состояние объекта - послать ему сообщение, в ответ на которое, объект может изменить собственное состояние.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Какие преимущества у ООП?

A

Преимущества ООП:
- Возможность легкой модификации (при грамотном анализе и проектировании)
- Возможность отката при наличии версий
- Более легкая расширяемость
- «Более естественная» декомпозиция (разделение целого на части) программного
обеспечения, которая существенно облегчает его разработку «слабая связанность кода».
- Сокращение количества межмодульных вызовов и уменьшение объемов информации,
передаваемой между модулями.
- Увеличивается показатель повторного использования кода.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Какие недостатки у ООП?

A

Недостатки ООП:
- Требуется другая квалификация
- Резко увеличивается время на анализ и проектирование систем
- Увеличение времени выполнения
- Размер кода увеличивается :interrobang:
- Неэффективно с точки зрения памяти (мертвый код - тот, который не используется)
-Сложность распределения работ на начальном этапе
- Себестоимость больше
- Скорость

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Назовите основные принципы ООП.

A

Инкапсуляция, наследование, полиморфизм, абстракция,

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Что такое инкапсуляция? (с примером)

A

Это свойство системы, позволяющее объединить данные и методы, работающие с ними, в классе и скрыть детали реализации от пользователя, открыв только то, что необходимо при последующем использовании.
Модификаторы доступа (Access modifiers: private, default (package visible), protected, public) Геттеры и Сеттеры (Getters and Setters)
Пример – кондиционер (берем пульт включаем холод - запускаются разные процессы, кот. не показываются пользователю), пользователю на пульте показывается температура воздуха на выходе, остальное все скрыто.
Цель инкапсуляции — уйти от зависимости внешнего интерфейса класса (то, что могут использовать другие классы) от реализации. Чтобы малейшее изменение в классе не влекло за собой изменение внешнего поведения класса.
Состояние объекта – это значение всех его полей. Объект не должен изменяться чем то из вне, кроме своих методов. Убрать возможность случайного/умышленного изменения объекта.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Что такое наследование?(С примером)

A

Наследование - свойство системы, позволяющее описать новый класс на основе уже существующего с частично или полностью заимствующейся функциональностью.
Наследование форма отношения «is a» (является). Класс наследника является классом предка, но класс предка не является классом наследника: собака – наследник животного, но животное не наследник собаки. Наследник – более «узкий» класс.
Пример: кондиционер наследуется от холодильной техники.
Есть одиночное и множественное наследование (класс наследуется от нескольких классов). В Jave множественное наследование ограничено. Проблема – ромбовидное наследование: у одного базового класса есть два наследника, а у наследника этих двух классов свой наследник, какая реализация попадет в последний – ХЗ.
Запретить наследование - public final class.
Делегирование – один класс вызывает другой класс, не связанный наследованием.
– это свойство системы, позволяющее описать новый класс на основе уже существующего с частично или полностью заимствующейся функциональностью.
Класс, от которого производится наследование, называется предком, базовым или
родительским. Новый класс – потомком, наследником или производным классом.
class Employee extends Person {}

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Что такое полиморфизм? (С примером

A

Полиморфизм - это свойство системы использовать объекты с одинаковым
интерфейсом без информации о типе и внутренней структуре объекта.
Все if –ы можно заменить на полиморфизм (способ рефакторинга).
Позволяет уменьшать размер программы.
Пример: интерфейс «охлаждать» имеет место в технике, холодное пиво)) и т.п.
Преимуществом полиморфизма является то, что он помогает снижать сложность программ,
разрешая использование одного и того же интерфейса для задания единого набора действий.
Выбор же конкретного действия, в зависимости от ситуации, возлагается на компилятор языка
программирования. Отсюда следует ключевая особенность полиморфизма - использование
объекта производного класса, вместо объекта базового (потомки могут изменять родительское
поведение, даже если обращение к ним будет производиться по ссылке родительского типа).
Unit ref = new Refrigerator(“ref”, 24);
Полиморфная переменная, это переменная, которая может принимать значения разных типов,
а полиморфная функция - функция у которой хотя бы один аргумент является полиморфной
переменной. Выделяют два вида полиморфных функций:
- ad hoc, функция ведет себя по разному для разных типов аргументов (например, функция
draw() — рисует по разному фигуры разных типов);
- параметрический, функция ведет себя одинаково для аргументов разных типов (например,
функция add() — одинаково кладет в контейнер элементы разных типов).
Абстрагирование – это способ выделить набор общих характеристик объекта, исключая из
рассмотрения частные и незначимые. Соответственно, абстракция – это набор всех таких
характеристик. (телефон звонил в 19 веке и в 21, функция выделена из разных сложных процессов).
Объект-класс-абстрактный класс-Интерфейс (макс. уровень абстракции).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Что такое ассоциация, агрегация и композиция?

A

Ассоциация обозначает связь между объектами. Композиция и агрегация – частные случаи ассоциации «часть-целое».
Агрегация предполагает, что объекты связаны взаимоотношением «part-of» (часть).
Композиция более строгий вариант агрегации. Дополнительно к требованию «part-of»
накладывается условие, что экземпляр «части» может входить только в одно целое (или
никуда не входить), в то время как в случае агрегации экземпляр «части» может входить в
несколько целых.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Расскажите про раннее (статическое) и позднее (динамическое) связывание.

A

Присоединение вызова метода к телу метода называется связыванием. Если связывание проводится компилятором (компоновщиком) перед запуском программы, то оно называется статическим или ранним связыванием (early binding).
В свою очередь, позднее связывание (late binding) – это связывание, проводимое непосредственно во время выполнения программы в зависимости от типа объекта. Позднее связывание также называют динамическим (dynamic), или связыванием на стадиивыполнения (runtime binding).
Для всех методов Java используется механизм позднего (динамического) связывания, если
только метод не был объявлен как final (приватные методы являются final по умолчанию).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

SOLID

A

Принципы SOLID - это набор руководящих принципов, предложенных Робертом Мартином (также известным как Uncle Bob), которые помогают создавать более гибкие, понятные и легко поддерживаемые программные системы. Эти принципы спроектированы для облегчения разработки и сопровождения кода в объектно-ориентированных языках программирования. Вот основные принципы SOLID:

**Принцип единственной ответственности **(Single Responsibility Principle - SRP):
Каждый класс должен иметь только одну причину для изменения. Суть заключается в том, что класс должен быть ответственным только за один аспект функциональности.

Принцип открытости/закрытости (Open/Closed Principle - OCP):
Программные сущности, такие как классы, модули и функции, должны быть открыты для расширения, но закрыты для модификации. Это означает, что вы должны иметь возможность добавлять новую функциональность без изменения существующего кода.

Принцип подстановки Барбары Лисков (Liskov Substitution Principle - LSP):
Объекты базового класса должны быть заменяемыми объектами производного класса без изменения правильности программы. Если класс является подклассом другого класса, то его объекты должны вести себя так же, как объекты базового класса.

Принцип разделения интерфейса (Interface Segregation Principle - ISP):
Клиенты не должны зависеть от интерфейсов, которые они не используют. Это означает, что не следует насаждать классам зависимость от интерфейсов, которые они не используют.

Принцип инверсии зависимостей (Dependency Inversion Principle - DIP):
Модули верхнего уровня не должны зависеть от модулей нижнего уровня, а оба типа модулей должны зависеть от абстракций. Абстракции не должны зависеть от деталей; детали должны зависеть от абстракций. Это также подразумевает использование интерфейсов или абстрактных классов для определения общих концепций, а не зависимость от конкретных реализаций.

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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Какая основная идея языка?

A

Кроссплатформенность, «написано/скомпилировано однажды, запускается везде» (compile once, run anywhere)
Приложения Java обычно транслируются в специальный байт-код, поэтому они могут работать на любой компьютерной архитектуре, для которой существует реализация виртуальной Java-машины.
Байт-код Java — набор инструкций, исполняемых виртуальной машиной Java. Каждый код операции байт-кода — один байт. Используются не все 256 возможных значений кодов операций. 51 из них зарезервированы для использования в будущем.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

За счет чего обеспечивается кроссплатформенность?

A

Java Virtual Machine (JVM) — виртуальная машина Java — основная часть исполняющей системы Java, так называемой Java Runtime Environment (JRE). Виртуальная машина Java исполняет байт-код Java, предварительно созданный из исходного текста Java-программы компилятором Java (javac). JVM может также использоваться для выполнения программ, написанных на других языках программирования. Например, исходный код на языке Ada может
быть скомпилирован в байт-код Java, который затем может выполниться с помощью JVM.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Какие преимущества у java?

A
  • Объектно-ориентированный: все является объектом. Дополнение может быть легко расширено
  • Платформонезависимый
  • Простой для понимания: основные концепции ООП
  • Безопасным: методы проверки подлинности основаны на шифровании с открытым ключом.
  • Архитектурно-нейтральным: компилятор генерирует архитектурно-нейтральные объекты формата файла, что делает скомпилированный код исполняемым на многих процессорах, с наличием системе Java Runtime.
  • Портативный: архитектурно-нейтральный и не имеющий зависимости от реализации аспектов спецификаций — все это делает Java портативным. Компилятор в Java написан на ANSI C с чистой
    переносимостью, который является подмножеством POSIX.
  • Прочный: прилагает усилия, чтобы устранить ошибки в различных ситуациях, делая упор в основном на время компиляции, проверку ошибок и проверку во время выполнения.
  • Язык для распределенного программирования и комфортной удаленной совместной работы.
    Специфическая для Java методология распределенных вычислений называется Remote Method Invocation (RMI). RMI позволяет использовать все преимущества Java: безопасность, независимость от платформы и объектно-ориентированное программирование для распределенных вычислений
  • Автоматическое управление памятью
  • Многопоточность
  • Стабильность и сообщество
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Какие недостатки у Java?

A
  • Платное коммерческое использование. Oracle с 2019 взимает плату за использование Java Standard Edition 8 в «коммерческих целях»
  • Низкая производительность (из-за компиляции и абстракции с помощью виртуальной машины, очистки памяти, взаимная блокировка потоков)
  • Отсутствие нативного дизайна для создания графического интерфейса пользователя (GUI). Есть Swing, SWT, JavaFX, JSF …но не катят.
  • Многословный и сложный код. длинные, чрезмерно сложные предложения затрудняют чтение и просмотр кода. Как и естественные языки, многие языки программирования высокого уровня содержат лишнюю информацию.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q
  1. Что такое JDK? Что в него входит?
A

Комплект разработчика приложений на языке Java:
- компилятор Java (javac)
- стандартные библиотеки классов Java, примеры, документацию, утилиты (вспомогательная компьютерная программа в составе общего программного обеспечения для выполнения специализированных типовых задач, связанных с работой оборудования и операционной системы)
- исполнительную систему Java (JRE: Java Virtual Machine + библиотеки Java-классов).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Что такое JRE? что в него входит?

A

Java Runtime Environment (JRE среда выполнения для Java) — минимальная реализация виртуальной машины, необходимая для исполнения Java-приложений, без компилятора и других средств разработки: Java Virtual Machine + и библиотеки Java-классов.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q
  1. Что такое JVM?
A

Основная часть JRE. Исполняет байт-код Java, предварительно созданный из исходного текста Java-программы компилятором Java (javac). JVM может также использоваться для выполнения программ, написанных на других языках программирования. Например, исходный код на языке Ada может быть скомпилирован в байт-код Java, который затем может выполниться с помощью JVM

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q

Что такое byte code?

A

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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
19
Q

Что такое загрузчик классов (classloader)?

A

Загрузчик классов является частью JRE, которая динамически закгружает Java классы в JVM. Обычно классы загружаются только по запросу. Система исполнения в Java не должна знать о файлах и файловых системах благодаря загрузчику классов. Делегирование является важной концепцией, которую выполняет загрузчик.
Загрузчик классов отвечает за поиск библиотек, чтение их содержимого и загрузку классов, содержащихся в библиотеках. Эта загрузка обычно выполняется «по требованию», поскольку она не происходит до тех пор, пока программа не вызовет класс. Класс с именем может быть загружен только один раз данным загрузчиком классов.
При запуске JVM, используются три загрузчика классов:
* Bootstrap class loader (Загрузчик класса Bootstrap)
* Extensions class loader (Загрузчик класса расширений)
* System class loader (Системный загрузчик классов)
Загрузчик класса Bootstrap загружает основные библиотеки Java, расположенные в
папке <JAVA_HOME>/jre/lib. Этот загрузчик является частью ядра JVM, написан на нативном коде.
Загрузчик класса расширений загружает код в каталоги расширений (<JAVA_HOME>/jre/lib/ext, или любой другой каталог, указанный системным свойством java.ext.dirs).
Системный загрузчик загружает код, найденный в java.class.path, который сопоставляется с переменной среды CLASSPATH. Это реализуется классом sun.misc.Launcher$AppClassLoader.
Загрузчик классов выполняет три основных действия в строгом порядке:
* Загрузка: находит и импортирует двоичные данные для типа.
* Связывание: выполняет проверку, подготовку и (необязательно) разрешение.
o Проверка: обеспечивает правильность импортируемого типа.
o Подготовка: выделяет память для переменных класса и инициализация памяти значениями по умолчанию.
o Разрешение: преобразует символические ссылки из типа в прямые ссылки.
* Инициализация: вызывает код Java, который инициализирует переменные класса их правильными начальными значениями.
Пользовательский загрузчик классов
Загрузчик классов написан на Java. Поэтому возможно создать свой собственный загрузчик классов, не понимая тонких деталей JVM. У каждого загрузчика классов Java есть родительский загрузчик классов, определенный при создании экземпляра нового загрузчика классов или в качестве системного загрузчика
классов по умолчанию для виртуальной машины.
Что делает возможным следующее:
* загружать или выгружать классы во время выполнения (например, динамически загружать библиотеки во время выполнения, даже из ресурса HTTP). Это важная особенность для:
o реализация скриптовых языков;
o использование bean builders;
o добавить пользовательскую расширение;
o позволяя нескольким пространствам имен общаться. Например, это одна из основ протоколов CORBA / RMI;
* изменить способ загрузки байт-кода (например, можно использовать зашифрованный байт-код
класса Java);
* модифицировать загруженный байт-код (например, для переплетения аспектов во время загрузки при использовании аспектно-ориентированного программирования);</JAVA_HOME></JAVA_HOME>

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
20
Q

Что такое JIT?

A

JIT-компиляция (англ. Just-in-time compilation, компиляция «на лету»), динамическая
компиляция (англ. dynamic translation) — технология увеличения производительности программных систем, использующих байт-код, путём компиляции байт-кода в машинный код или в другой формат непосредственно во время работы программы

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
21
Q

Что такое сборщик мусора? (Garbage collector)

A

Способ автоматического управления памятью.
Сборщик мусора (Garbage Collector) должен делать всего две вещи:
- Находить мусор - неиспользуемые объекты. (Объект считается неиспользуемым, если ни одна из сущностей в коде, выполняемом в данный момент, не содержит ссылок на него, либо цепочка ссылок, которая могла бы связать объект с некоторой сущностью приложения, обрывается);
- Освобождать память от мусора.
Работа сборщика мусора не бесплатная, она оплачивается ресурсами компьютера и задержками в выполнении программы.
Существует два подхода к обнаружению мусора:
* Reference counting;
* Tracing
Reference counting (подсчёт ссылок). Суть этого подхода состоит в том, что каждый объект имеет счетчик. Счетчик хранит информацию о том, сколько ссылок указывает на объект. Когда ссылка уничтожается, счетчик уменьшается. Если значение счетчика равно нулю, - объект можно считать мусором. Главным минусом такого подхода является сложность обеспечения точности
счетчика. Также при таком подходе сложно выявлять циклические зависимости (когда два объекта указывают друг на друга, но ни один живой объект на них не ссылается), что приводит к утечкам памяти.
Tracing (трассировка) - живыми могут считаться только те объекты, до которых мы можем добраться из корневых точек (GC Root) и те объекты, которые доступны с живого объекта. Всё остальное - мусор.
Существует 4 типа корневых точки:
* Локальные переменные и параметры методов;
* Потоки;
* Статические переменные;
* Ссылки из JNI.
Самое простое java приложение будет иметь корневые точки:
* Локальные переменные внутри main() метода и параметры main() метода;
* Поток который выполняет main();
* Статические переменные класса, внутри которого находится main() метод.
Таким образом, если мы представим все объекты и ссылки между ними как дерево, то нам нужно будет пройти с корневых узлов (точек) по всем рёбрам. При этом узлы, до которых мы сможем добраться - не мусор, все остальные - мусор. При таком подходе циклические зависимости легко выявляются. HotSpot VM использует именно такой подход.
Для очистки памяти от мусора существуют два основных метода:
* Copying collectors
* Mark-and-sweep
При copying collectors подходе память делится на две части «from-space» и «to-space», при этом сам принцип работы такой:
* Объекты создаются в «from-space»;
* Когда «from-space» заполняется, приложение приостанавливается;
* Запускается сборщик мусора. Находятся живые объекты в «from-space» и копируются в «to-space»;
* Когда все объекты скопированы «from-space» полностью очищается;
* «to-space» и «from-space» меняются местами.
Главный плюс такого подхода в том, что объекты плотно забивают память. Минусы подхода:
1. Приложение должно быть остановлено на время, необходимое для полного
прохождения цикла сборки мусора;
2. В худшем случае (когда все объекты живые) «form-space» и «to-space» будут
обязаны быть одинакового размера.
Алгоритм работы mark-and-sweep можно описать так:
* Объекты создаются в памяти;
* В момент, когда нужно запустить сборщик мусора приложение приостанавливается;
* Сборщик проходится по дереву объектов, помечая живые объекты;
* Сборщик проходится по всей памяти, находя все не отмеченные куски памяти и сохраняя их в «free list»;
* Когда новые объекты начинают создаваться они создаются в памяти доступной во «free list».
Минусы этого способа:
1. Приложение не работает пока происходит сборка мусора;
2. Время остановки напрямую зависит от размеров памяти и количества объектов;
3. Если не использовать «compacting» память будет использоваться не эффективно.
Сборщики мусора HotSpot VM используют комбинированный подход Generational Garbage Collection, который позволяет использовать разные алгоритмы для разных этапов сборки мусора.
Этот подход опирается на том, что:
* большинство создаваемых объектов быстро становятся мусором;
* существует мало связей между объектами, которые были созданы в прошлом и только что созданными объектами.
Как работает сборщик мусора?
Механизм сборки мусора - это процесс освобождения места в куче, для возможности добавления новых объектов.
Объекты создаются посредством оператора new, тем самым присваивая объекту ссылку. Для окончания работы с объектом достаточно просто перестать на него ссылаться, например, присвоив переменной ссылку на другой объект или значение null; прекратить выполнение метода, чтобы его
локальные переменные завершили свое существование естественным образом. Объекты, ссылки на которые отсутствуют, принято называть мусором (garbage), который будет удален.
Виртуальная машина Java, применяя механизм сборки мусора, гарантирует, что любой объект, обладающий ссылками, остается в памяти — все объекты, которые недостижимы из исполняемого кода, ввиду отсутствия ссылок на них, удаляются с высвобождением отведенной для них памяти.
Точнее говоря, объект не попадает в сферу действия процесса сборки мусора, если он достижим посредством цепочки ссылок, начиная с корневой (GC Root) ссылки, т.е. ссылки, непосредственно существующей в выполняемом коде.
Память освобождается сборщиком мусора по его собственному «усмотрению». Программа может успешно завершить работу, не исчерпав ресурсов свободной памяти или даже не приблизившись к этой черте и поэтому ей так и не потребуются «услуги» сборщика мусора.
Мусор собирается системой автоматически, без вмешательства пользователя или
программиста, но это не значит, что этот процесс не требует внимания вовсе. Необходимость создания и удаления большого количества объектов существенным образом сказывается на производительности приложений и если быстродействие программы является важным фактором, следует тщательно обдумывать решения, связанные с созданием объектов, — это, в свою очередь,
уменьшит и объем мусора, подлежащего утилизации.
Какие разновидности сборщиков мусора реализованы в виртуальной машине HotSpot?
Java HotSpot VM предоставляет разработчикам на выбор четыре различных сборщика мусора:
* Serial (последовательный) — самый простой вариант для приложений с небольшим объемом
данных и не требовательных к задержкам. На данный момент используется сравнительно редко, но на
слабых компьютерах может быть выбран виртуальной машиной в качестве сборщика по умолчанию.
Использование Serial GC включается опцией -XX:+UseSerialGC.
* Parallel (параллельный) — наследует подходы к сборке от последовательного сборщика, но добавляет параллелизм в некоторые операции, а также возможности по автоматической подстройке под требуемые параметры производительности. Параллельный сборщик включается опцией - XX:+UseParallelGC.
* Concurrent Mark Sweep (CMS) — нацелен на снижение максимальных задержек путем выполнения части работ по сборке мусора параллельно с основными потоками приложения. Подходит для работы с относительно большими объемами данных в памяти. Использование CMS GC включается опцией -XX:+UseConcMarkSweepGC.
* Garbage-First (G1) — создан для замены CMS, особенно в серверных приложениях, работающих на многопроцессорных серверах и оперирующих большими объемами данных. G1 включается опцией Java - XX:+UseG1GC.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
22
Q

Что такое Heap и Stack память в Java? Чем они отличаются?

A

Heap (куча) используется Java Runtime для выделения памяти под объекты и классы. Создание нового объекта также происходит в куче. Это же является областью работы сборщика мусора. Любой объект, созданный в куче, имеет глобальный доступ и на него могут ссылаться из любой части
приложения.
Stack (стек) это область хранения данных также находящееся в общей оперативной памяти (RAM) только для одного потока. Всякий раз, когда вызывается метод, в памяти стека создается новый блок, который содержит примитивы и ссылки на другие объекты в методе. Как только метод заканчивает работу, блок также перестает использоваться, тем самым предоставляя доступ для следующего
метода. Размер стековой памяти намного меньше объема памяти в куче. Стек в Java работает по схеме LIFO (Последний-зашел-Первый-вышел)
https://tproger.ru/translations/programming-concepts-stack-and-heap/
Различия между Heap и Stack памятью:
● Куча используется всеми частями приложения в то время как стек используется только одним потоком исполнения программы.
● Всякий раз, когда создается объект, он всегда хранится в куче, а в памяти стека содержится лишь ссылка на него. Память стека содержит только локальные переменные примитивных типов и
ссылки на объекты в куче.
● Объекты в куче доступны с любой точке программы, в то время как стековая память не может быть доступна для других потоков, только для одного потока.
● Стековая память существует лишь какое-то время работы программы, а память в куче живет с самого начала до конца работы программы.
● Если память стека полностью занята, то Java Runtime бросает исключение
java.lang.StackOverflowError. Если заполнена память кучи, то бросается исключение
java.lang.OutOfMemoryError: Java Heap Space.
● Размер памяти стека намного меньше памяти в куче.
● Из-за простоты распределения памяти, стековая память работает намного быстрее кучи.
Для определения начального и максимального размера памяти в куче используются -Xms и -Xmx опции JVM. Для стека определить размер памяти можно с помощью опции -Xss.
Размер стека задаётся при создании потока, и у каждой переменной есть максимальный размер, зависящий от типа данных, размер кучи ограничен оперативной памятью.
Верно ли утверждение, что примитивные типы данных всегда хранятся в стеке, а
экземпляры ссылочных типов данных в куче? Не совсем. Примитивное поле экземпляра класса хранится не в стеке, а в куче. Любой объект (всё,
что явно или неявно создаётся при помощи оператора new) хранится в куче.
Каким образом передаются переменные в методы, по значению или по ссылке?
В Java параметры всегда передаются только по значению, что определяется как «скопировать значение и передать копию». С примитивами это будет копия содержимого. Со ссылками - тоже копия содержимого, т.е. копия ссылки. При этом внутренние члены ссылочных типов через такую копию изменить возможно, а вот саму ссылку, указывающую на экземпляр - нет.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
23
Q

Какие примитивные типы данных есть в Java?

A

boolean, char, byte, short, int, long, float, double
boolean 1 bit NA false boolean bool = true;
char 16 bits Символы Unicode ‘\u0000′ или 0 char c = ‘A’;
byte 8 bits [-128,127] или [-2^7 to 2^7-1] 0 byte b = 10; byte b = 0b010;
short 16 bits [-32768,32767] 0 short s = 32; short s = ‘A’;
int 32 bits [-2147483648,2147483647] 0 int i = 10; int i = ‘A’;
long 64 bits [-2^63,2^63-1] 0 long l = 3200L; long l = 3200;
float 32 bits [-3.4E38, 3.4E38] 0.0f float f = (float) 12.34; float f = 12.34f;
double 64 bits [-1.7E308, 1.7E308] 0.0 double d = 12.34;

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
24
Q

Что такое char? по умолчанию?

A

char — \u0000;
char - 16-разрядное беззнаковое целое, представляющее собой символ UTF-16 (буквы и
цифры)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
25
Q

Сколько памяти занимает boolean?

A

32 бита - булеан

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
26
Q

Что такое классы-обертки?

A

Значение примитива становится объектом, чтобы выполнять различные операции ( .parseInt()). Примитивы не имеют методов. Объекты классов-оберток являются неизменяемыми (Immutable).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
27
Q

Что такое автоупаковка и автораспаковка?

A

Для присваивания ссылок-примитивов объектам их классов-оберток (и наоборот) не требуется ничего делать, все происходит автоматически int x = 7; Integer y = 111;
x = y; // автораспаковка y = x * 123; // автоупаковка Автоупаковка и распаковка не работают для массивов.
Автоупаковка - это механизм неявной инициализации объектов классов-оберток (Byte, Short,Integer, Long, Float, Double, Character, Boolean) значениями соответствующих им исходных примитивных типов (byte, short, int…), без явного использования конструктора класса.
Автоупаковка происходит при прямом присваивании примитива классу-обертке (с помощью оператора =), либо при передаче примитива в параметры метода (типа класса-обертки).
Автоупаковке в классы-обертки могут быть подвергнуты как переменные примитивных типов, так и константы времени компиляции (литералы и final-примитивы). При этом литералы должны быть синтаксически корректными для инициализации переменной исходного примитивного типа.
Автоупаковка переменных примитивных типов требует точного соответствия типа исходного примитива типу класса-обертки. Например, попытка упаковать переменную типа byte в Short, без предварительного явного приведения byte в short вызовет ошибку компиляции.
Автоупаковка констант примитивных типов допускает более широкие границы соответствия. В этом случае компилятор способен предварительно осуществлять неявное расширение/сужение типа примитивов:
неявное расширение/сужение исходного типа примитива до типа примитива соответствующего классу-обертке (для преобразования int в Byte, сначала компилятор самостоятельно неявно сужает int к byte) автоупаковку примитива в соответствующий класс-обертку. Однако, в этом случае существуют два
дополнительных ограничения: a) присвоение примитива обертке может производится только оператором = (нельзя передать такой примитив в параметры метода без явного приведения типов) b) тип левого операнда не должен быть старше чем Character, тип правого не должен старше, чем int:
допустимо расширение/сужение byte в/из short, byte в/из char, short в/из char и только сужение byte из int, short из int, char из int. Все остальные варианты требуют явного приведения типов).
Дополнительной особенностью целочисленных классов-оберток созданных автоупаковкой констант в диапазоне -128 … +127 является то, что они кэшируются JVM. Поэтому такие обертки с одинаковыми значениями будут являться ссылками на один объект.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
28
Q

Что такое явное и неявное приведение типов? В каких случаях в java нужно
использовать явное приведение? примеры

A

Каждое выражение и каждая переменная имеет строго определенный тип уже на момент компиляции. Механизм приведения типов (casting) - способ преобразования значения переменной одного типа в значение другого типа:
Неявные – выполняются автоматически (расширяющие преобразования, сужающие с потерей данных: int->float, long->float, long->double).
byte b = 7;
int d = b; // преобразование от byte к int
Явные – надо указывать тип (сужающие преобразования от типа с большей разрядностью к типу с меньшей разрядностью). Потеря данных (старшие биты будут потеряны).
Разновидности приведения:
- Тождественное (identity). Преобразование выражения любого типа к точно такому же типу всегда допустимо и происходит автоматически.
- Расширение (повышение, upcasting) примитивного типа (widening primitive). Означает, что осуществляется переход от менее емкого типа к более ёмкому. Например, от типа byte (длина 1 байт) к типу int (длина 4 байта). Такие преобразование безопасны в том смысле, что новый тип всегда гарантировано вмещает в себя все данные, которые хранились в старом типе и таким
образом не происходит потери данных. Этот тип приведения всегда допустим и происходит автоматически.
- Сужение (понижение, downcasting) примитивного типа (narrowing primitive). Означает, что переход осуществляется от более емкого типа к менее емкому. При таком преобразовании есть риск потерять данные. Например, если число типа int было больше 127, то при приведении его к byte значения битов старше восьмого будут потеряны. В Java такое преобразование должно совершаться явным образом, при этом все старшие биты, не умещающиеся в новом типе, просто
отбрасываются - никакого округления или других действий для получения более корректного результата не производится.
- Расширение объектного типа (widening reference). Означает неявное восходящее приведение типов или переход от более конкретного типа к менее конкретному, т.е. переход от потомка к предку. Разрешено всегда и происходит автоматически.
- Сужение объектного типа (narrowing reference). Означает нисходящее приведение, то есть приведение от предка к потомку (подтипу). Возможно только если исходная переменная является подтипом приводимого типа. При несоответствии типов в момент выполнения выбрасывается исключение ClassCastException. Требует явного указания типа.
- Преобразование к строке (to String). Любой тип может быть приведен к строке, т.е. к экземпляру класса String.
- Запрещенные преобразования (forbidden). Не все приведения между произвольными типами допустимы. Например, к запрещенным преобразованиям относятся приведения от любого ссылочного типа к примитивному и наоборот (кроме преобразования к строке). Кроме того невозможно привести друг к другу классы находящиеся на разных ветвях дерева наследования и
т.п.
При приведении ссылочных типов с самим объектом ничего не происходит, - меняется лишь тип ссылки, через которую происходит обращение к объекту.
Для проверки возможности приведения нужно воспользоваться оператором instanceof:
Parent parent = new Child();
if (parent instanceof Child) {
Child child = (Child) parent;
}

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
29
Q

Что такое пул интов?

A

Для более эффективного использования памяти, в джаве используются так называемые пулы.
Есть строковый пул, Integer pool итд. Когда мы создаем объект не используя операцию new, объект
помещается в пул, и в последствии, если мы захотим создать такой же объект (опять не используя
new), новый объект создан не будет, а мы просто получим ссылку на наш объект из пула.
Особенность Integer-пула — он хранит только числа, которые помещаются в тип данных byte:
от -128 до 127. Для остальных чисел пул не работает.
Integer i1 = 127;
Integer i2 = 127;
Integer i3 = 128;
Integer i4 = 128;
System.out.println(i1==i2);//true
System.out.println(i3==i4);//false

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
30
Q

Какие нюансы у строк в Java?

A

● Это неизменяемый (immutable) (не меняется после создания) и финализированный (без
потомков) тип данных; потокобезопасный может использоваться в многопоточке
● Все объекты класса String JVM хранит в пуле строк;
● Объект класса String можно получить используя двойные кавычки;
● Можно использовать оператор + для конкатенации строк;
● Начиная с Java 7 строки можно использовать в конструкции switch.
* Каждый объект можно привести к строке .toString
Cтроки представляют собой массив символов (так было до Java 9).
Начиная с Java 9 строки хранятся как массив байт.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
31
Q

Что такое пул строк?

A

Стринг хранит под капотом в виде массива байтов
Пул строк – это набор строк хранящийся в Heap.
Пул строк возможен благодаря неизменяемости строк в Java и реализации идеи
интернирования строк;
Пул строк помогает экономить память, но по этой же причине создание строки занимает большевремени; Когда для создания строки используются “, то сначала ищется строка в пуле с таким же значением, если находится, то просто возвращается ссылка, иначе создается новая строка в пуле, а затем возвращается ссылка на неё;
String habr = “habrahabr”; - “строковый литерал”
При использовании оператора new создается новый объект String. Затем при помощи метода intern() эту строку можно поместить в пул или же получить из пула ссылку на другой объект String с таким же значением;
Пул строк является примером паттерна «Приспособленец» (Flyweight).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
32
Q

Почему не рекомендуется изменять строки в цикле? Что рекомендуется
использовать?

A

Применить StringBuilder до цикла, в цикле .append
String s5 = “I’m “;
String s6 = “ + Java developer”;
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 8; i++) {
System.out.println(sb.append(s5).append(s6));
}

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
33
Q

Почему строки не рекомендуется использовать для хранения паролей?

A

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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
34
Q

Почему String неизменяемый и финализированный класс?

A

Пул строк возможен только потому, что строка неизменяемая, таким образом виртуальная машина сохраняет больше свободного места в Heap, поскольку разные строковые переменные указывают на одну и ту же переменную в пуле. Если бы строка была изменяемой, то интернирование строк не было бы возможным, потому что изменение значения одной переменной отразилось бы также и на остальных переменных, ссылающихся на эту строку.
* Если строка будет изменяемой, тогда это станет серьезной угрозой безопасности приложения. Например, имя пользователя базы данных и пароль передаются строкой для получения соединения с базой данных и в программировании сокетов реквизиты хоста и порта передаются строкой. Так как строка неизменяемая, её значение не может быть изменено, в противном случае злоумышленник
может изменить значение ссылки и вызвать проблемы в безопасности приложения.
* Неизменяемость позволяет избежать синхронизации: строки безопасны для многопоточности и один экземпляр строки может быть совместно использован различными потоками.
* Строки используются classloader-ом и неизменность обеспечивает правильность загрузки класса.
* Поскольку строка неизменяемая, её hashCode() кэшируется в момент создания и нет необходимости рассчитывать его снова. Это делает строку отличным кандидатом для ключа в HashMap т.к. егообработка происходит быстрее.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
35
Q

Почему строка является популярным ключом в HashMap в Java?

A

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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
36
Q

Что делает метод intern() в классе String?

A

Метод intern() используется для сохранения строки в пуле строк или получения ссылки, если
такая строка уже находится в пуле.
String q = “I’m”;
String w = “I’m”;
String r = new String(“I’m”);
String t = r.intern();
System.out.println(“q==w: “+(q==w)); //true
System.out.println(“q==r: “+(q==r)); //false
System.out.println(“q==t: “+(q==t)); //true

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
37
Q

Можно ли использовать строки в конструкции switch?

A

Да, начиная с Java 7 в операторе switch можно использовать строки, ранние версии Java не поддерживают этого. При этом:
- участвующие строки чувствительны к регистру;
- используется метод equals() для сравнения полученного значения со значениями case, поэтому во избежание NullPointerException стоит предусмотреть проверку на null.
- согласно документации Java 7 для строк в switch, компилятор Java формирует более эффективный байткод для строк в конструкции switch, чем для сцепленных условий if-else.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
38
Q

Какая основная разница между String, StringBuffer, StringBuilder?

A

Класс String является неизменяемым (immutable) - модифицировать объект такого класса нельзя, можно лишь заменить его созданием нового экземпляра.
Класс StringBuffer изменяемый - использовать StringBuffer следует тогда, когда необходимо часто модифицировать содержимое. Потокобезопасный. Синхронизированные методы работают медленнее не сихнронизированных.
Класс StringBuilder был добавлен в Java 5 и он во всем идентичен классу StringBuffer за исключением того, что он не синхронизирован и поэтому его методы выполняются значительно быстрей.
Класс StringJoiner используется, чтобы создать последовательность строк, разделенных разделителем с возможностью присоединить к полученной строке префикс и суффикс:
StringJoiner joiner = new StringJoiner(“.”, “prefix-“, “-suffix”);
for (String s : “Hello the brave world”.split(“ “)) {
joiner.add(s);
}
System.out.println(joiner); //prefix-Hello.the.brave.world-suffix

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
39
Q

Существуют ли в java многомерные массивы?

A

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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
40
Q

Какими значениями инициируются переменные по умолчанию?

A

Числа инициализируются 0 или 0.0;
char — \u0000;
boolean — false;
Объекты (в том числе String) — null.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
41
Q

Что такое сигнатура метода?

A

Название метода и типы параметров в определенном порядке
public void method(double a, int b)
Контракт метода - эксепшены

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
42
Q

Расскажите про метод main если местами поменять паблик и статик – все норм
запуститься? можно запускать без маина прогу.

A

Можно поменять, да запуститься.
Можно было запустить в Java 6 и более ранних версиях статическим блоком с exit(). Теперь нет.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
43
Q

Каким образом переменные передаются в методы, по значению или по ссылке?

A

int х = 3;
int у = х; “скопировать значение внутри х и записать эту копию в у”
Java передает параметры по значению. Всегда.
Cat A = new Cat ();
Cat B = A;
Ссылка А копируется в ссылку B. К объекту это не относится — у вас по прежнему всего одинобъект.
Но теперь у вас есть две различных ссылки, контролирующие один и тот же объект Cat.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
44
Q

Какие виды классов есть в java?

A

Top level class (Обычный класс):
- Abstract class (Абстрактный класс);
-Final class (Финализированный класс).
Interfaces (Интерфейс).
Enum (Перечисление).
Nested class (Вложенный класс):
-Static nested class (Статический вложенный класс);
-Member inner class (Простой внутренний класс);
-Local inner class (Локальный класс);
-Anonymous inner class (Анонимный вложенный класс).
К классам верхнего уровня модификатор static неприменим.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
45
Q

Расскажите про вложенные классы. В каких случаях они применяются?

A

Класс называется вложенным (Nested class), если он определен внутри другого класса.
Вложенный класс должен создаваться только для того, чтобы обслуживать обрамляющий его
класс. Если вложенный класс оказывается полезен в каком-либо ином контексте, он должен
стать классом верхнего уровня. Вложенные классы имеют доступ ко всем (в том числе
приватным) полям и методам внешнего класса, но не наоборот. Из-за этого разрешения
использование вложенных классов приводит к некоторому нарушению инкапсуляции.
Существуют четыре категории вложенных классов:
+ Static nested class (Статический вложенный класс);
+ Member inner class (Простой внутренний класс);
+ Local inner class (Локальный класс);
+ Anonymous inner class (Анонимный класс).
Такие категории классов, за исключением первого, также называют внутренними (Inner class).
Внутренние классы ассоциируются не с внешним классом, а с экземпляром внешнего.
Каждая из категорий имеет рекомендации по своему применению:
● Не статический: если вложенный класс должен быть виден за пределами одного метода или
он слишком длинный для того, чтобы его можно было удобно разместить в границах одного метода
и если каждому экземпляру такого класса необходима ссылка на включающий его экземпляр.
● Статический: если ссылка на обрамляющий класс не требуется.
Доступ к полям стат. и нестат. класса
● Локальный: если класс необходим только внутри какого-то метода и требуется создавать
экземпляры этого класса только в этом методе.
● Анонимный: если к тому же применение класса сводится к использованию лишь в одном
месте и уже существует тип, характеризующий этот класс.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
46
Q

Что такое «локальный класс»? Каковы его особенности?

A

Local inner class (Локальный класс) - это вложенный класс, который может быть декларированв любом блоке, в котором разрешается декларировать переменные. Как и простые внутренниеклассы (Member inner class) локальные классы имеют имена и могут использоваться многократно.
Как и анонимные классы, они имеют окружающий их экземпляр только тогда, когда применяются внестатическом контексте.
Локальные классы имеют следующие особенности:
● Видны только в пределах блока, в котором объявлены;
● Не могут быть объявлены как private/public/protected или static;
● Не могут иметь внутри себя статических объявлений (полей, методов, классов);
● Имеют доступ к полям и методам обрамляющего класса;
● Могут обращаться к локальным переменным и параметрам метода, если они объявлены с модификатором final.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
47
Q

Что такое «анонимные классы»? Где они применяются?

A

Это вложенный локальный класс без имени, который разрешено декларировать в любом месте обрамляющего класса, разрешающем размещение выражений. Создание экземпляра анонимного класса происходит одновременно с его объявлением. В зависимости от местоположения анонимный класс ведет себя как статический либо как нестатический вложенный класс - в нестатическом контексте появляется окружающий его экземпляр.
Анонимные классы имеют несколько ограничений:
● Их использование разрешено только в одном месте программы - месте его создания;
● Применение возможно только в том случае, если после порождения экземпляра нет необходимости на него ссылаться;
● Реализует лишь методы своего интерфейса или суперкласса, т.е. не может объявлять каких- либо новых методов, так как для доступа к ним нет поименованного типа.
Анонимные классы обычно применяются для:
● создания объекта функции (function object), например реализация интерфейса Comparator;
● создания объекта процесса (process object), такого как экземпляры классов Thread, Runnable и подобных;
● в статическом методе генерации;
● инициализации открытого статического поля final, которое соответствует сложному перечислению типов, когда для каждого экземпляра в перечислении требуется отдельный подкласс.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
48
Q

Каким образом из вложенного класса получить доступ к полю внешнего класса?

A

Статический вложенный класс имеет прямой доступ только к статическим полям
обрамляющего класса.
Простой внутренний класс, может обратиться к любому полю внешнего класса напрямую. В случае, если у вложенного класса уже существует поле с таким же литералом, то обращаться к такому полю следует через ссылку на его экземпляр. Например: Outer.this.field.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
49
Q

Что такое перечисления (enum)?

A

Перечисления представляют набор логически связанных констант. Объявление перечисления происходит с помощью оператора enum, после которого идет название перечисления. Затем идет список элементов перечисления через запятую. Каждый из них явно объявлен как открытый статический финальный член класса. values(). Он возвращает массив всех констант перечисления
Особенности Enum классов:
1) Конструктор всегда private или default
2) Могут имплементировать интерфейсы
3) Не могут наследовать класс
4) Можем переопределить toString()
5) Нет public конструктора, поэтому нельзя создать экземпляр вне Enum
6) При equals() выполняется ==
7) ordinal() возвращает порядок элементов
8) Может использоваться в TreeSet и TreeMap т.к. Enum имплементирует Comparable
9) compareTo() имитирует порядок элементов предоставляемый ordinal()
10) Можно использовать в Switch Case
11) values() возвращает массив всех констант
12) Легко создать потокобезопасный синглтон без double check volatile переменных.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
50
Q

Как проблема ромбовидного наследования решена в java?

A

Интерфейсы

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
51
Q

Что такое конструктор по умолчанию?

A

Если у какого-либо класса не определить конструктор, то компилятор сгенерирует конструктор без аргументов - так называемый «конструктор по умолчанию».
Если вы создали сами конструктор, то конструктор по умолчанию использоваться не будет(если он не создан).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
52
Q

Могут ли быть приватные конструкторы? Для чего они нужны?

A

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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
53
Q

Расскажите про классы-загрузчики и про динамическую загрузку классов.

A

Основа работы с классами в Java — классы-загрузчики, обычные Java-объекты, предоставляющие интерфейс для поиска и создания объекта класса по его имени во время работы приложения.
В начале работы программы создается 3 основных загрузчика классов:
* базовый загрузчик (bootstrap/primordial). Загружает основные системные и внутренние классы JDK (Core API - пакеты java.* (rt.jar и i18n.jar) . Важно заметить, что базовый загрузчик является «Изначальным» или «Корневым» и частью JVM, вследствие чего его нельзя создать внутри кода программы.
* загрузчик расширений (extention). Загружает различные пакеты расширений, которые располагаются в директории <JAVA_HOME>/lib/ext или другой директории, описанной в системном параметре java.ext.dirs. Это позволяет обновлять и добавлять новые расширения без необходимости модифицировать настройки используемых приложений. Загрузчик расширений реализован классом sun.misc.Launcher$ExtClassLoader.
* системный загрузчик (system/application). Загружает классы, пути к которым указаны в переменной окружения CLASSPATH или пути, которые указаны в командной строке запуска JVM после ключей -classpath или -cp. Системный загрузчик реализован классом sun.misc.Launcher$AppClassLoader.
Загрузчики классов являются иерархическими: каждый из них (кроме базового) имеет родительский загрузчик и в большинстве случаев, перед тем как попробовать загрузить класс самостоятельно, он посылает вначале запрос родительскому загрузчику загрузить указанный класс. Такое делегирование
позволяет загружать классы тем загрузчиком, который находится ближе всего к базовому в иерархии делегирования. Как следствие поиск классов будет происходить в источниках в порядке их доверия:
сначала в библиотеке Core API, потом в папке расширений, потом в локальных файлах CLASSPATH.
Процесс загрузки класса состоит из трех частей:
* Loading – на этой фазе происходит поиск и физическая загрузка файла класса в определенном источнике (в зависимости от загрузчика). Этот процесс определяет базовое представление класса в памяти. На этом этапе такие понятия как «методы», «поля» и т.д. пока не известны.
* Linking – процесс, который может быть разбит на 3 части:
o Bytecode verification – проверка байт-кода на соответствие требованиям, определенным в спецификации JVM.
o Class preparation – создание и инициализация необходимых структур, используемых для представления полей, методов, реализованных интерфейсов и т.п., определенных в загружаемом классе.
o Resolving – загрузка набора классов, на которые ссылается загружаемый класс.
* Initialization – вызов статических блоков инициализации и присваивание полям класса значений по умолчанию.
Динамическая загрузка классов в Java имеет ряд особенностей:
* отложенная (lazy) загрузка и связывание классов. Загрузка классов производится только при необходимости, что позволяет экономить ресурсы и распределять нагрузку.
* проверка корректности загружаемого кода (type safeness). Все действия связанные с контролем использования типов производятся только во время загрузки класса, позволяя избежать дополнительной нагрузки во время выполнения кода.
* программируемая загрузка. Пользовательский загрузчик полностью контролирует процесс получения запрошенного класса — самому ли искать байт-код и создавать класс или делегировать создание другому загрузчику. Дополнительно существует возможность выставлять различные атрибуты
безопасности для загружаемых классов, позволяя таким образом работать с кодом из ненадежных источников.
* множественные пространства имен. Каждый загрузчик имеет своё пространство имён для создаваемых классов. Соответственно, классы, загруженные двумя различными загрузчиками на основе общего байт-кода, в системе будут различаться.
Существует несколько способов инициировать загрузку требуемого класса:
* явный: вызов ClassLoader.loadClass() или Class.forName() (по умолчанию используется загрузчик, создавший текущий класс, но есть возможность и явного указания загрузчика);
* неявный: когда для дальнейшей работы приложения требуется ранее не использованный класс, JVM инициирует его загрузку.</JAVA_HOME>

54
Q

Чем отличаются конструкторы по-умолчанию, конструктор копирования и
конструктор с параметрами?

A

У конструктора по умолчанию отсутствуют какие-либо аргументы. Конструктор копирования принимает в качестве аргумента уже существующий объект класса для последующего создания его клона. Конструктор с параметрами имеет в своей сигнатуре аргументы (обычно необходимые для инициализации полей класса).

55
Q

Какие модификаторы доступа есть в Java? Какие применимы к классам паблик
дефолт?

A
  • private (приватный): члены класса доступны только внутри класса.
  • default, package-private, package level (доступ на уровне пакета): видимость класса/членов класса только внутри пакета. Является модификатором доступа по умолчанию
  • protected (защищённый): члены класса доступны внутри пакета и в наследниках.
  • public (публичный): класс/члены класса доступны всем.
    Во время наследования возможно изменения модификаторов доступа в сторону большей видимости (для поддержания соответствия принципу подстановки Барбары Лисков).
56
Q

Что означает модификатор static?

A

Модификатор, применяемый к полю, блоку, методу, внутреннему классу.
Данный модификатор указывает на привязку субъекта к текущему классу

57
Q

Может ли статический метод быть переопределён или перегружен?

A

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

58
Q

Могут ли нестатические методы перегрузить статические?

A

да, могут

59
Q

Можно ли сузить уровень доступа/тип возвращаемого значения при
переопределении метода?

A

При переопределении метода сужать модификатор доступа не разрешается, т.к. это приведет к нарушению принципа подстановки Барбары Лисков. Расширение уровня доступа возможно.
Можно изменять все, что не мешает компилятору понять какой метод родительского класса имеется в виду:
Изменять тип возвращаемого значения при переопределении метода разрешено только в сторону сужения типа (вместо родительского класса - наследника).
При изменении типа, количества, порядка следования аргументов вместо переопределения будет происходить overloading (перегрузка) метода.
Секцию throws метода можно не указывать, но стоит помнить, что она остаётся
действительной, если уже определена у метода родительского класса. Также, возможно добавлять новые исключения, являющиеся наследниками от уже объявленных или исключения RuntimeException. Порядок следования таких элементов при переопределении значения не имеет.

60
Q

Что можно изменить в сигнатуре метода при переопределении? Можно ли
менять модификаторы (throws и тп)?

A

При изменении типа, количества, порядка следования аргументов вместо переопределения будет происходить overloading (перегрузка) метода.
Секцию throws метода можно не указывать, но стоит помнить, что она остаётся
действительной, если уже определена у метода родительского класса. Также, возможно добавлять новые исключения, являющиеся наследниками от уже объявленных или исключения RuntimeException. Порядок следования таких элементов при переопределении значения не имеет.

61
Q

Могут ли классы быть статическими? да

A

Объект статического класса не хранит ссылку на конкретный экземпляр внешнего класса.
Объект статического вложенного класса вполне может существовать сам по себе.
Статический вложенный класс может обращаться только к статическим полям и методам внешнего класса.
Объекты статического класса не содержат ссылок на объекты внешнего класса. А самих объектов мы можем создать сколько угодно.

62
Q

Что означает модификатор final? К чему он может быть применим?

A

Модификатор final может применяться к переменным, параметрам методов, полям и методам класса или самим классам.
● Класс не может иметь наследников;
● Метод не может быть переопределен в классах наследниках;
● Поле не может изменить свое значение после инициализации;
● Параметры методов не могут изменять своё значение внутри метода;
● Локальные переменные не могут быть изменены после присвоения им значения.

63
Q

Что такое абстрактные классы? Чем они отличаются от обычных?

A

Класс помеченный модификатором abstract называется абстрактным классом. Такие классы
могут выступать только предками для других классов. Создавать экземпляры самого абстрактного
класса не разрешается. При этом наследниками абстрактного класса могут быть как другие
абстрактные классы, так и классы, допускающие создание объектов.
Метод помеченный ключевым словом abstract - абстрактный метод, т.е. метод, который не
имеет реализации. Если в классе присутствует хотя бы один абстрактный метод, то весь класс
должен быть объявлен абстрактным.
Использование абстрактных классов и методов позволяет описать некий шаблон объекта,
который должен быть реализован в других классах. В них же самих описывается лишь некое общее
для всех потомков поведение.
НА ЗАМЕТКУ!!!
Особенности абстрактных классов:
1) Может быть конструктор (для вызовов по цепочке из наследников)
2) Имплементят интерфейсы, но не обязаны реализовывать их методы
3) Не могут быть final
4) Могут содержать static методы
5) Нельзя создать объект
6) Абстрактные методы могут отсутствовать
7) Может содержать метод main()
8) Классы-наследники не обязаны реализовывать все абстрактные методы

64
Q

Может ли быть абстрактный класс без абстрактных методов?

A

Да

65
Q

Могут ли быть конструкторы у абстрактных классов? Для чего они нужны?

A

Да, может быть конструктор (для вызовов по цепочке из наследников)

66
Q

Что такое интерфейсы? Какие модификаторы по умолчанию имеют поля и
методы интерфейсов?

A

Ключевое слово interface используется для создания полностью абстрактных классов.
Основное предназначение интерфейса - определять каким образом мы можем использовать класс, который его реализует. Создатель интерфейса определяет имена методов, списки аргументов и типы возвращаемых значений, но не реализует их поведение. Все методы неявно объявляются как
public.
Начиная с Java 8 в интерфейсах разрешается размещать реализацию методов по умолчанию default и статических static методов.
Интерфейс также может содержать и поля. В этом случае они автоматически являются публичными public, статическими static и неизменяемыми final.
**Что такое static метод интерфейса?
**Статические методы интерфейса похожи на методы по умолчанию, за исключением того, что для них отсутствует возможность переопределения в классах, реализующих интерфейс.
Статические методы в интерфейсе являются частью интерфейса без возможности
использовать их для объектов класса реализации;
Методы класса java.lang.Object нельзя переопределить как статические;
Статические методы в интерфейсе используются для обеспечения спомогательных методов, например, проверки на null, сортировки коллекций и т.д.

67
Q
  1. Чем интерфейсы отличаются от абстрактных классов? В каких случаях следует
    использовать абстрактный класс, а в каких интерфейс?
A
  • has a – интерфейс, is a- абстр класс
  • Интерфейс описывает только поведение. У него нет состояния. А у абстрактного класса состояние есть: он описывает и то, и другое
  • Абстрактный класс связывает между собой и объединяет классы, имеющие очень близкую связь (птицы: голуби, воробьи). В то же время, один и тот же интерфейс могут реализовать классы,
    у которых вообще нет ничего общего (Flyable: птицы, наркоман, самолет).
  • Классы могут реализовывать сколько угодно интерфейсов, но наследоваться можно только от одного класса
68
Q

Может ли один интерфейс наследоваться от другого? От двух других?

A

да, да

69
Q

Что такое дефолтные методы интерфейсов? Для чего они нужны?

A

Если класс реализует интерфейс, он может, но не обязан, реализовать методы по-умолчанию, уже реализованные в интерфейсе. Класс наследует реализацию по умолчанию.
Дефолтные методы можно переопределить.
Если некий класс реализует несколько интерфейсов, которые имеют одинаковый метод по умолчанию, то класс должен реализовать метод с совпадающей сигнатурой самостоятельно.
Ситуация аналогична, если один интерфейс имеет метод по умолчанию, а в другом этот же метод является абстрактным - никакой реализации по умолчанию классом не наследуется.
Метод по умолчанию не может переопределить метод класса java.lang.Object.
Помогают реализовывать интерфейсы без страха нарушить работу других классов.
Позволяют избежать создания служебных классов, так как все необходимые методы могут быть представлены в самих интерфейсах.
Дают свободу классам выбрать метод, который нужно переопределить.
Одной из основных причин внедрения методов по умолчанию является возможность коллекций в Java 8 использовать лямбда-выражения.

70
Q

Как решается проблема ромбовидного наследования при наследовании интерфейсов при наличии default методов?

A

Обязательным переопределением default-метода.
В случае, если вызывается default-метод из интерфейса, его обязательно надо будет переопределить.

71
Q

Каков порядок вызова конструкторов инициализации с учетом иерархии классов?

A

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

72
Q

Зачем нужны и какие бывают блоки инициализации?

A

Блоки инициализации представляют собой код, заключенный в фигурные скобки и размещаемый внутри класса вне объявления методов или конструкторов.
Существуют статические и нестатические блоки инициализации.
Блок инициализации выполняется перед инициализацией класса загрузчиком классов или созданием объекта класса с помощью конструктора.
Несколько блоков инициализации выполняются в порядке следования в коде класса.
Блок инициализации способен генерировать исключения, если их объявления перечислены в throws всех конструкторов класса.
Блок инициализации возможно создать и в анонимном классе.
Используются для выполнения кода, который должен выполняться один раз при инициализации класса.

73
Q

Для чего используются статические блоки инициализации?

A

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

74
Q

Где разрешена инициализация статических/нестатических полей?

A

Статические поля можно инициализировать при объявлении, в статическом или нестатическом блоке инициализации.
Нестатические поля можно инициализировать при объявлении, в нестатическом блоке инициализации или в конструкторе.

75
Q

Что произойдет, если в блоке инициализации возникнет исключительная ситуация?

A

Для нестатических блоков инициализации, если выбрасывание исключения прописано явным образом, требуется, чтобы объявления этих исключений были перечислены в throws всех конструкторов класса (в контракте конструктора). Иначе будет ошибка компиляции.
В остальных случаях взаимодействие с исключениями будет проходить так же, как и в любом другом месте. Класс не будет инициализирован, если ошибка происходит в статическом блоке, и объект класса не будет создан, если ошибка возникает в нестатическом блоке.
Для статического блока выбрасывание исключения в явном виде приводит к ошибке компиляции ExceptionInizialazionError.

76
Q

Какое исключение выбрасывается при возникновении ошибки в блоке
инициализации класса?

A

Если возникшее исключение – наследник Error:
* для статических блоков инициализации будет выброшено
java.lang.ExceptionInInitializerError;
* для нестатических будет проброшено исключение-источник.
Если возникшее исключение – наследник Error, то в обоих случаях будет выброшено java.lang.Error.
Если исключение java.lang.ThreadDeath (смерть потока), то в этом случае никакое исключение выброшено не будет.

77
Q

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

A

Все классы являются наследниками суперкласса Object. Это не нужно указывать явно. В результате объект Object может ссылаться на объект любого другого класса.

78
Q

Какие методы есть у класса Object (перечислить все)? Что они делают?

A

Object – это базовый класс для всех остальных объектов в Java. Любой класс наследуется от Object и, соответственно, наследуют его методы:
* public boolean equals(Object obj) – служит для сравнения объектов по значению;
* int hashCode() – возвращает hash-код для объекта;
* String toString() – возвращает строковое представление объекта;
* Class getClass() – возвращает класс объекта во время выполнения;
* protected Object clone() – создает и возвращает копию объекта;
* void notify() – возобновляет поток, ожидающий монитор;
* void notifyAll() – возобновляет все потоки, ожидающие монитор;
* void wait() – остановка вызвавшего метод потока до момента, пока другой поток не вызовет метод notify() или notifyAll() для этого объекта;
* void wait(long timeout) – остановка вызвавшего метод потока на определенноевремя или пока другой поток не вызовет метод notify() или notifyAll() для этого объекта;
* void wait(long timeout, int nanos) – остановка вызвавшего метод потока на определенное время или пока другой поток не вызовет метод notify() или notifyAll() для этого объекта;
* protected void finalize() – может вызываться сборщиком мусора в момент удаления объекта при сборке мусора.

79
Q

Расскажите про equals и hashcode

A

Хеш-код – это целочисленный результат работы метода, которому в качестве входного параметра передан объект. Рассчитывается по нативному методу.
Equals – это метод, определенный в Object, который служит для сравнения объектов. При сравнении объектов при помощи == идет сравнение по ссылкам. При сравнении по equals() идет сравнение по состояниям объектов (по умолчанию случайным образом, но
есть другие варианты).
По умолчанию ссылки, чтобы его использовать, нужно переопределить (на область в памяти), т. к. при == сравниваются ссылки, а equals сравнивает состояния:
Свойства equals():
* Рефлексивность: для любой ссылки на значение x, x.equals(x) вернет true;
* Симметричность: для любых ссылок на значения x и y, x.equals(y) должно вернуть true, тогда и только тогда, когда y.equals(x) возвращает true.
* Транзитивность: для любых ссылок на значения x, y и z, если x.equals(y) и y.equals(z) возвращают true, тогда и x.equals(z) вернет true;
* Непротиворечивость: для любых ссылок на значения х и у, если несколько раз вызвать х.equals(y), постоянно будет возвращаться значение true либо постоянно будет возвращаться значение false при условии, что никакая информация, используемая при сравнении объектов, не поменялась;
* Совместимость с hashCode(): два тождественно равных объекта должны иметь одно и то же значение hashCode().
При переопределении equals() обязательно нужно переопределить метод hashCode().
Равные объекты должны возвращать одинаковые хэш коды.

80
Q

Каким образом реализованы методы hashCode() и equals() в классе Object?

A
  1. Реализация метода Object.equals() сводится к проверке на равенство двух ссылок:
    public boolean equals(Object obj) {
    return (this == obj);
    }
  2. Реализация метода Object.hashCode() описана как native, т. е. определенной не с помощью Java-кода и обычно возвращает адрес объекта в памяти:
    public native int hashCode();
81
Q

Зачем нужен equals(). Чем он отличается от операции ==?

A

Метод equals() определяет отношение эквивалентности объектов.
При сравнение объектов с помощью == сравнение происходит лишь между ссылками.
При сравнении по переопределенному разработчиком equals() – по внутреннему состоянию объектов.

82
Q

Правила переопределения метода Object.equals()

A

Использование оператора == для проверки, является ли аргумент ссылкой на указанный объект. Если является, возвращается true. Если сравниваемый объект == null, должно вернуться false.
* Использование оператора instanceof и вызова метода getClass() для проверки, имеет ли аргумент правильный тип. Если не имеет, возвращается false.
* Приведение аргумента к правильному типу. Поскольку эта операция следует за проверкой instanceof она гарантированно будет выполнена.
* Обход всех значимых полей класса и проверка того, что значение поля в текущем объекте и значение того же поля в проверяемом на эквивалентность аргументе соответствуют друг другу. Если проверки для всех полей прошли успешно, возвращается результат true, в противном случае – false.
* По окончанию переопределения метода equals() следует проверить: является ли порождаемое отношение эквивалентности рефлексивным, симметричным, транзитивным и непротиворечивым? Если ответ отрицательный, метод подлежит соответствующей правке.

83
Q

Что будет, если переопределить equals(), не переопределяя hashCode()?
Какие могут возникнуть проблемы?

A

Классы и методы, которые используют правила этого контракта, могут работать некорректно.
Так для HashMap это может привести к тому, что пара «ключ-значение», которая была в нее помещена, при использовании нового экземпляра ключа не будет в ней найдена.

84
Q

Какой контракт между hashCode() и equals()?

A
  1. Если два объекта возвращают разные значения hashcode(), то они не могут быть равны.
  2. Если equals объектов true, то и хеш-коды должны быть равны.
  3. Переопределив equals, всегда переопределять и hashcode.
85
Q

Для чего нужен метод hashCode()?

A

Метод hashCode() необходим для вычисления хеш-кода переданного в качестве входного параметра объекта. В Java это целое число, в более широком смысле – битовая строка фиксированной длины, полученная из массива произвольной длины. Этот метод реализован
таким образом, что для одного и того же входного объекта хеш-код всегда будет одинаковым.
Следует понимать, что в Java множество возможных хеш-кодов ограничено типом int, а множество объектов ничем не ограничено. Из-за этого вполне возможна ситуация, что хеш-коды разных объектов могут совпасть:
* если хеш-коды разные, то и объекты гарантированно разные;
* если хеш-коды равны, то объекты могут не обязательно равны.
В случае, если hashCode() не переопределен, то будет выполнятся его реализация по умолчанию из класса Object: для разных объектов будет разный хеш-код.
Значение int может быть в диапазоне 232, при переопределении хеш-кода можно использовать отрицательное значение.

86
Q

Правила переопределения метода hashcode()

A
  1. Если хеш-коды разные, то и входные объекты гарантированно разные.
  2. Если хеш-коды равны, то входные объекты не всегда равны.
  3. При вычислении хеш-кода следует использовать те же поля, которые сравниваются вequals и которые не вычисляются на основе других значений.
87
Q

Есть ли какие-либо рекомендации о том, какие поля следует использовать при подсчете hashCode()?

A

Следует выбирать поля, которые с большой долью вероятности будут различаться. Для этого необходимо использовать уникальные, лучше всего примитивные поля, например такие как id, uuid. При этом нужно следовать правилу: если поля задействованы при вычислении hashCode(), то они должны быть задействованы и при выполнении equals().

88
Q

Могут ли у разных объектов быть одинаковые hashCode()?

A

Да, могут. Метод hashCode() не гарантирует уникальность возвращаемого значения.
Ситуация, когда у разных объектов одинаковые хеш-коды называется коллизией.
Вероятность возникновения коллизии зависит от используемого алгоритма генерации хеш-кода.

89
Q

Почему нельзя реализовать hashcode(), который будет гарантированно
уникальным для каждого объекта?

A

В Java множество возможных хеш-кодов ограничено типом int, а множество объектов ничем не ограничено.
Из-за этого вполне возможна ситуация, что хеш-коды разных объектов могут совпасть.

90
Q

Почему хеш-код в виде 31 * x + y предпочтительнее чем x + y?

A
  • множитель создает зависимость значения хеш-кода от очередности обработки полей, что в итоге порождает лучшую хеш-функцию;
  • 31 можно легко сдвигать побитово;
  • в хеш-коде должны фигурировать поля, которые фигурируют в equals().
91
Q

Чем a.getClass().equals(A.class) отличается от a instanceOf A.class?

A

getClass() получает только класс, а оператор instanceof проверяет, является ли объект экземпляром класса или его потомком.
instanceof
Оператор instanceof сравнивает объект и указанный тип. Его можно использовать для проверки, является ли данный объект экземпляром некоторого класса, либо экземпляром его дочернего класса, либо экземпляром класса, который реализует указанный интерфейс.
this.getClass() == that.getClass() проверяет два класса на идентичность, поэтому для корректной реализации контракта метода equals() необходимо использовать точное сравнение с помощью метода getClass().

92
Q

Что такое исключение?

A

Исключение – это ошибка (является объектом), возникающая во время выполнения программы.

93
Q

Опишите иерархию исключений

A

Исключения делятся на несколько классов, но все они имеют общего предка – класс Throwable, потомками которого являются классы Exception и Error.
Ошибки (Errors) представляют собой более серьезные проблемы, которые, согласно спецификации Java, не следует обрабатывать в собственной программе, поскольку они связаны с проблемами уровня JVM. Например, исключения такого рода возникают, если закончилась память, доступная виртуальной машине.
Исключения (Exceptions) являются результатом проблем в программе, которые в принципе решаемы, предсказуемы и последствия которых возможно устранить внутри программы. Например, произошло деление целого числа на ноль.

94
Q

**

Расскажите про обрабатываемые и необрабатываемые исключения

A

В Java все исключения делятся на два типа:
* checked (контролируемые/проверяемые исключения) должны обрабатываться блоком catch или описываться в сигнатуре метода (например throws IOException), наличие такого обработчика/модификатора сигнатуры проверяются на этапе компиляции;
* unchecked (неконтролируемые/непроверяемые исключения), к которым относятся ошибки Error (например OutOfMemoryError), обрабатывать которые не рекомендуется и исключения времени выполнения, представленные классом RuntimeException и его наследниками (например NullPointerException), которые
могут не обрабатываться блоком catch и не быть описанными в сигнатуре метода.

95
Q

Можно ли обработать необрабатываемые исключения?

A

Можно, чтобы в некоторых случаях программа не прекратила работу. Отлавливаются в trycatch.

96
Q

Какой оператор позволяет принудительно выбросить исключение?

A

Это оператор throw:
throw new Exception();

97
Q

О чем говорит ключевое слово throws?

A

Модификатор throws прописывается в сигнатуре метода и указывает на то, что метод потенциально может выбросить исключение с указанным типом.
Передает обработку исключения вышестоящему методу. Используется в конструкторе, методе, классе.

98
Q

Как написать собственное («пользовательское») исключение?

A

Необходимо унаследоваться от базового класса требуемого типа исключений (например, от Exception или RuntimeException) и переопределить методы.

99
Q

Какие существуют unchecked exception?

A

Наиболее часто встречающиеся: ArithmeticException, ClassCastException, ConcurrentModificationException, IllegalArgumentException, IllegalStateException, IndexOutOfBoundsException, NoSuchElementException, NullPointerException, UnsupportedOperationException.

100
Q

Что представляет из себя ошибки класса Error?

A

Ошибки класса Error представляют собой наиболее серьезные проблемы уровня JVM.
Например, исключения такого рода возникают, если закончилась память, доступная виртуальной машине. Обрабатывать такие ошибки не запрещается, но делать этого не рекомендуется.

101
Q

Что вы знаете о OutOfMemoryError?

A

OutOfMemoryError выбрасывается, когда виртуальная машина Java не может создать (разместить) объект из-за нехватки памяти, а сборщик мусора не может высвободить достаточное ее количество.
Область памяти, занимаемая java-процессом, состоит из нескольких частей. Тип OutOfMemoryError зависит от того, в какой из них не хватило места:
* java.lang.OutOfMemoryError: Java heap space: не хватает места в куче, а именно, в области памяти, в которую помещаются объекты, создаваемые в приложении программно. Обычно проблема кроется в утечке памяти. Размер задается параметрами -Xms и -Xmx.
* java.lang.OutOfMemoryError: PermGen space (до версии Java 8): Данная ошибка возникает при нехватке места в Permanent-области, размер которой задается параметрами -XX:PermSize и -XX:MaxPermSize.
* java.lang.OutOfMemoryError: GC overhead limit exceeded: Данная ошибка может возникнуть как при переполнении первой, так и второй областей. Связана она с тем, что памяти осталось мало и сборщик мусора постоянно работает, пытаясь высвободить немного места. Данную ошибку можно отключить с помощью параметра -XX:-UseGCOverheadLimit.
* java.lang.OutOfMemoryError: unable to create new native thread: Выбрасывается, когда нет возможности создавать новые потоки.

102
Q

Опишите работу блока try-catch-finally

A

try – данное ключевое слово используется для отметки начала блока кода, который потенциально может привести к ошибке.
catch – ключевое слово для отметки начала блока кода, предназначенного для перехвата и обработки исключений в случае их возникновения.
finally – ключевое слово для отметки начала блока кода, который является дополнительным. Этот блок помещается после последнего блока catch. Управление передается в блок finally в
любом случае, было выброшено исключение или нет.
Общий вид конструкции для обработки исключительной ситуации выглядит следующим
образом:
try {
//код, который потенциально может привести к исключительной ситуации
}
catch(SomeException e) { //в скобках указывается класс конкретной ожидаемой ошибки
//код обработки исключительной ситуации
}
finally {
//необязательный блок, код которого выполняется в любом случае
}

103
Q

Возможно ли использование блока try-finally (без catch)?

A

Такая запись допустима, но смысла в такой записи не так много, все же лучше иметь блок catch, в котором будет обрабатываться необходимое исключение.
Работает точно так же: после выхода из блока try выполняется блок finally.

104
Q

Может ли один блок catch отлавливать сразу несколько исключений?

A

В Java 7 стала доступна новая языковая конструкция, с помощью которой можно перехватывать несколько исключений одним блоком catch:
try {
//…
} catch(IOException | SQLException ex) {
//…
}

105
Q

Всегда ли исполняется блок finally? Существуют ли ситуации, когда блок finally не будет выполнен?

A

Да, кроме случаев завершения работы программы или JVM:
* Finally может не выполниться в случае если в блоке try вызывает System.exit(0).
* Runtime.getRuntime().exit(0), Runtime.getRuntime().halt(0) и если во время исполнения блока try виртуальная машина выполнила недопустимую операцию и будет закрыта.
* В блоке try{} бесконечный цикл.

106
Q

Может ли метод main() выбросить исключение во вне и если да, то где
будет происходить обработка данного исключения?

A

Может, исключение будет передано в виртуальную машину Java (JVM).

107
Q

В каком порядке следует обрабатывать исключения в catch-блоках?

A

От наследника к предку.

108
Q

Что такое механизм try-with-resources?

A

Данная конструкция, которая появилась в Java 7, позволяет использовать блок try-catch, не заботясь о закрытии ресурсов, используемых в данном сегменте кода. Ресурсы объявляются
в скобках сразу после try, а компилятор уже сам неявно создает секцию finally, в которой и происходит освобождение занятых в блоке ресурсов. Под ресурсами подразумеваются сущности, реализующие интерфейс java.lang.Autocloseable.
Стоит заметить, что блоки catch и явный finally выполняются уже после того, как закрываются ресурсы в неявном finally.

109
Q

Что произойдет, если исключение будет выброшено из блока catch, после чего другое исключение будет выброшено из блока finally?

A

finally-секция может «перебить» throw/return при помощи другого throw/return.

110
Q

Что произойдет, если исключение будет выброшено из блока catch, после чего другое исключение будет выброшено из метода close() при
использовании try-with-resources?

A

В try-with-resources добавлена возможность хранения «подавленных» исключений, и брошенное try-блоком исключение имеет больший приоритет, чем исключения, получившиеся во время закрытия.

111
Q

Предположим, есть метод, который может выбросить IOException и
FileNotFoundException. В какой последовательности должны идти блоки catch? Сколько блоков catch будет выполнено?

A

Общее правило: обрабатывать исключения нужно от младшего к старшему. Т. е. нельзя поставить в первый блок catch(Exception ex) {}, иначе все дальнейшие блоки catch() уже ничего не смогут обработать, т. к. любое исключение будет соответствовать обработчику
catch(Exception ex).
Таким образом, исходя из факта, что FileNotFoundException extends IOException сначала нужно обработать FileNotFoundException, а затем уже IOException:
void method() {
try {
//…
} catch (FileNotFoundException ex) {
//…
} catch (IOException ex) {
//…
}
}

112
Q

Что такое «сериализация» и как она реализована в Java?

A

Сериализация (Serialization) – процесс преобразования структуры данных в линейную последовательность байтов для дальнейшей передачи или сохранения. Сериализованные
объекты можно затем восстановить (десериализовать).
В Java, согласно спецификации Java Object Serialization, существует два стандартных способа сериализации: стандартная сериализация через использование интерфейса java.io.Serializable и «расширенная» сериализация – java.io.Externalizable. Сериализация позволяет в определенных пределах изменять класс. Вот наиболее важные
изменения, с которыми спецификация Java Object Serialization может справляться автоматически:
* добавление в класс новых полей;
* изменение полей из статических в нестатические;
* изменение полей из транзитных в нетранзитные.
Обратные изменения (из нестатических полей в статические и из нетранзитных в транзитные) или удаление полей требуют определенной дополнительной обработки в зависимости от того, какая степень обратной совместимости необходима.

113
Q

Для чего нужна сериализация?

A

Для компактного сохранения состояния объекта и считывание этого состояния.

114
Q

Опишите процесс сериализации/десериализации с использованием Serializable

A

При использовании Serializable применяется алгоритм сериализации, который с помощью рефлексии (Reflection API) выполняет:
* запись в поток метаданных о классе, ассоциированном с объектом (имя класса, идентификатор SerialVersionUID, идентификаторы полей класса);
* рекурсивную запись в поток описания суперклассов до класса java.lang.Object (не включительно);
* запись примитивных значений полей сериализуемого экземпляра, начиная с полей самого верхнего суперкласса;
* рекурсивную запись объектов, которые являются полями сериализуемого объекта. При этом ранее сериализованные объекты повторно не сериализуются, что позволяет алгоритму корректно работать с циклическими ссылками.
Для выполнения десериализации под объект выделяется память, после чего его поля заполняются значениями из потока. Конструктор объекта при этом не вызывается. Однако при десериализации будет вызван конструктор без параметров родительского несериализуемого класса, а его отсутствие повлечет ошибку десериализации.

115
Q

Как изменить стандартное поведение сериализации/десериализации?

A

Реализовать интерфейс java.io.Externalizable, который позволяет применение пользовательской логики сериализации. Способ сериализации и десериализации описывается в методах writeExternal() и readExternal(). Во время десериализации вызывается
конструктор без параметров, а потом уже на созданном объекте вызывается метод readExternal.
Если у сериализуемого объекта реализован один из следующих методов, то механизм сериализации будет использовать его, а не метод по умолчанию :
* writeObject() – запись объекта в поток;
* readObject() – чтение объекта из потока;
* writeReplace() – позволяет заменить себя экземпляром другого класса перед записью;
* readResolve() – позволяет заменить на себя другой объект после чтения.

116
Q

Какие поля не будут сериализованы при сериализации? Будет ли
сериализовано final-поле?

A

Поля с модификатором transient. В таком случае после восстановления его значение будет null.
Поля static. Значения статических полей автоматически не сохраняются.
Поля с модификатором final сериализуются как и обычные. За одним исключением – их невозможно десериализовать при использовании Externalizable, поскольку final-поля должны быть инициализированы в конструкторе, а после этого в readExternal изменить
значение этого поля будет невозможно. Соответственно, если необходимо сериализовать объект с final-полем неоходимо использовать только стандартную сериализацию
(Serializable за счет рефлексии).
Если final-поля не кастомные, то будут десериализовываться.

117
Q

Как создать собственный протокол сериализации?

A

Для создания собственного протокола нужно переопределить writeExternal() и readExternal().
В отличие от двух других вариантов сериализации, здесь ничего не делается автоматически.
Протокол полностью в наших руках.
Для создания собственного протокола сериализации достаточно реализовать интерфейс Externalizable, который содержит два метода:
public void writeExternal(ObjectOutput out) throws IOException;
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;

118
Q

Какая роль поля serialVersionUID в сериализации?

A

serialVersionUID используется для указании версии сериализованных данных.
Если не объявить serialVersionUID в классе явно, среда выполнения Java делает это за нас, но этот процесс чувствителен ко многим метаданным класса, включая количество полей, тип
полей, модификаторы доступа полей, интерфейсов, которые реализованы в классе и пр.
Рекомендуется явно объявлять serialVersionUID т. к. при добавлении, удалении атрибутов класса динамически сгенерированное значение может измениться и в момент выполнения будет выброшено исключение InvalidClassException.
private static final long serialVersionUID = 20161013L;

119
Q

Когда стоит изменять значение поля serialVersionUID?

A

serialVersionUID нужно изменять при внесении в класс несовместимых изменений, например, при удалении какого-либо его атрибута.

120
Q

В чем проблема сериализации Singleton?

A

Проблема в том, что после десериализации получим другой объект. Таким образом, сериализация дает возможность создать Singleton еще раз, что недопустимо.
Существует два способа избежать этого:
* явный запрет сериализации;
* определение метода с сигнатурой (default/public/private/protected/) Object readResolve() throws ObjectStreamException, назначением которого станет возврат замещающего объекта вместо объекта, на котором он вызван.

121
Q

Как исключить поля из сериализации?

A

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

122
Q

Что обозначает ключевое слово transient?

A

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

123
Q

Какое влияние оказывают на сериализуемость модификаторы полей static и final?

A

При стандартной сериализации поля, имеющие модификатор static, не сериализуются.
Соответственно, после десериализации это поле значения не меняет. При использовании реализации Externalizable сериализовать и десериализовать статическое поле можно, но не
рекомендуется этого делать, т. к. это может сопровождаться трудноуловимыми ошибками. Поля с модификатором final сериализуются как и обычные. За одним исключением – их
невозможно десериализовать при использовании Externalizable, поскольку final-поля должны быть инициализированы в конструкторе, а после этого в readExternal() изменить значение
этого поля будет невозможно. Соответственно, если необходимо сериализовать объект с final-полем, необходимо использовать только стандартную сериализацию.

124
Q

Как не допустить сериализацию?

A

Чтобы не допустить автоматическую сериализацию, можно переопределить private методы
для создания исключительной ситуации NotSerializableException.
private void writeObject(ObjectOutputStream out) throws IOException {
throw new NotSerializableException();
}
private void readObject(ObjectInputStream in) throws IOException {
throw new NotSerializableException();
}
Любая попытка записать или прочитать этот объект теперь приведет к возникновению исключительной ситуации.

125
Q

Какие существуют способы контроля за значениями десериализованного объекта?

A

Если есть необходимость выполнения контроля за значениями десериализованного объекта, то можно использовать интерфейс ObjectInputValidation с переопределением метода validateObject().
Если вызвать метод validateObject() после десериализации объекта, то будет вызвано исключение InvalidObjectException при значении возраста за пределами 39…60.
public class Person implements java.io.Serializable,

java.io.ObjectInputValidation {

@Override
public void validateObject() throws InvalidObjectException {
if ((age < 39) || (age > 60))
throw new InvalidObjectException(“Invalid age”);
}
}
Также существуют способы подписывания и шифрования, позволяющие убедиться, что
данные не были изменены:
 с помощью описания логики в writeObject() и readObject();
 поместить в оберточный класс javax.crypto.SealedObject и/или
java.security.SignedObject. Данные классы являются сериализуемыми, поэтому при оборачивании объекта в SealedObject создается подобие «подарочной упаковки» вокруг исходного объекта. Для шифрования необходимо создать симметричный ключ, управление которым должно осуществляться отдельно. Аналогично для проверки данных можно использовать класс SignedObject, для работы с которым также нужен
симметричный ключ, управляемый отдельно.

126
Q

Расскажите про клонирование объектов

A

Использование оператора присваивания не создает нового объекта, а лишь копирует ссылку на объект. Таким образом, две ссылки указывают на одну и ту же область памяти, на один и тот же объект. Для создания нового объекта с таким же состоянием используется клонирование объекта.
Класс Object содержит protected метод clone(), осуществляющий побитовое копирование объекта производного класса. Однако сначала необходимо переопределить метод clone() как public для обеспечения возможности его вызова. В переопределенном методе следует
вызвать базовую версию метода super.clone(), которая и выполняет собственно клонирование.
Чтобы окончательно сделать объект клонируемым, класс должен реализовать интерфейс Cloneable. Интерфейс Cloneable не содержит методов, относится к маркерным интерфейсам, а его реализация гарантирует, что метод clone() класса Object возвратит
точную копию вызвавшего его объекта с воспроизведением значений всех его полей. В противном случае метод генерирует исключение CloneNotSupportedException. Следует отметить, что при использовании этого механизма объект создается без вызова конструктора.
Это решение эффективно только в случае, если поля клонируемого объекта представляют собой значения базовых типов и их оберток или неизменяемых (immutable) объектных типов. Если же поле клонируемого типа является изменяемым ссылочным типом, то для
корректного клонирования требуется другой подход. Причина заключается в том, что при создании копии оригинальное поле и его копия представляют собой ссылку на один и тот же объект. В этой ситуации следует также клонировать и сам объект поля класса.

Такое клонирование возможно только в случае, если тип атрибута класса также реализует интерфейс Cloneable и переопределяет метод clone(). Иначе вызов метода невозможен из-за
его недоступности. Отсюда следует, что если класс имеет суперкласс, то для реализации механизма клонирования текущего класса-потомка необходимо наличие корректной реализации такого механизма в суперклассе. При этом следует отказаться от использования
объявлений final для полей объектных типов по причине невозможности изменения их значений при реализации клонирования.
Помимо встроенного механизма клонирования в Java для клонирования объекта можно использовать:
* специализированный конструктор копирования – в классе описывается конструктор, который принимает объект этого же класса и инициализирует поля создаваемого объекта значениями полей переданного;
* фабричный метод – (factory method), который представляет собой статический метод, возвращающий экземпляр своего класса;
* механизм сериализации – сохранение и последующее восстановление объекта в/из потока байтов.

127
Q

В чем отличие между поверхностным и глубоким клонированием?

A

Поверхностное копирование копирует настолько малую часть информации об объекте, насколько это возможно. По умолчанию клонирование в Java является поверхностным, т. е. класс Object не знает о структуре класса, который он копирует. Клонирование такого типа осуществляется JVM по следующим правилам:
* если класс имеет только члены примитивных типов, то будет создана совершенно новая копия объекта и возвращена ссылка на этот объект;
* если класс помимо членов примитивных типов содержит члены ссылочных типов, то тогда копируются ссылки на объекты этих классов. Следовательно, оба объекта будут иметь одинаковые ссылки.
Глубокое копирование дублирует абсолютно всю информацию объекта:
* нет необходимости копировать отдельно примитивные данные;
* все члены ссылочного типа в оригинальном классе должны поддерживать клонирование, для каждого такого члена при переопределении метода clone() должен вызываться super.clone();
* если какой-либо член класса не поддерживает клонирование, то в методе клонирования необходимо создать новый экземпляр этого класса и скопировать каждый его член со всеми атрибутами в новый объект класса, по одному.

128
Q

Какой способ клонирования предпочтительней?

A

Наиболее безопасным и следовательно предпочтительным способом клонирования является использование специализированного конструктора копирования:
* отсутствие ошибок наследования (не нужно беспокоиться, что у наследников появятся новые поля, которые не будут склонированы через метод clone();
* поля для клонирования указываются явно;
* возможность клонировать даже final-поля.

129
Q

Почему метод clone() объявлен в классе Object, а не в интерфейсе Cloneable?

A

Метод clone() объявлен в классе Object с указанием модификатора native, чтобы обеспечить доступ к стандартному механизму поверхностного копирования объектов. Одновременно он
объявлен и как protected, чтобы нельзя было вызвать этот метод у не переопределивших его объектов. Непосредственно интерфейс Cloneable является маркерным (не содержит объявлений методов) и нужен только для обозначения самого факта, что данный объект
готов к тому, чтобы быть клонированным. Вызов переопределенного метода clone() у не Cloneable объекта вызовет выбрасывание CloneNotSupportedException.

130
Q

Как создать глубокую копию объекта (2 способа)?

A

Глубокое клонирование требует выполнения следующих правил:
* нет необходимости копировать отдельно примитивные данные;
* все классы-члены в оригинальном классе должны поддерживать клонирование, Для каждого члена класса должен вызываться super.clone() при переопределении метода clone();
* если какой-либо член класса не поддерживает клонирование, то в методе клонирования необходимо создать новый экземпляр этого класса и скопировать каждый его член со всеми атрибутами в новый объект класса, по одному.
Сериализация – это еще один способ глубокого копирования. Просто сериализуем нужный объект и десериализуем его. При этом объект должен поддерживать интерфейс Serializable. Сохраняем объект в массив байт и потом читаем из него.

131
Q

Рефлексия

A

Рефлексия (Reflection) – это механизм получения данных о программе во время ее выполнения (runtime). В Java Reflection осуществляется с помощью Java Reflection API, состоящего из классов пакетов java.lang и java.lang.reflect.
Возможности Java Reflection API:
* определение класса объекта;
* получение информации о модификаторах класса, полях, методах, конструкторах и суперклассах;
* определение интерфейсов, реализуемых классом;
* создание экземпляра класса;
* получение и установка значений полей объекта;
* вызов методов объекта;
* создание нового массива.

132
Q

Класс Optional

A

Опциональное значение Optional – это контейнер для объекта, который может содержать или не содержать значение null. Такая обертка является удобным средством предотвращения NullPointerException, т. к. имеет некоторые функции высшего порядка, избавляющие от добавления повторяющихся проверок if null/notNull.