Основы языка
Возможности Java, метод main, примитивы и обёртки, static и instance, final/finally/finalize.
9 вопросов
JuniorТеорияОчень частоJava передаёт аргументы по значению или по ссылке при вызове метода?
Java передаёт аргументы по значению или по ссылке при вызове метода?
Java всегда передаёт по значению — передачи по ссылке в языке нет. Для примитива в параметр копируется само значение. Для объекта копируется ссылка, поэтому параметр указывает на тот же самый объект и метод может менять его состояние через неё. Но переприсваивание параметра перепривязывает только эту локальную копию, так что переменная вызывающего по-прежнему ссылается на исходный объект.
Типичные ошибки
- ✗Называть передачу объектов передачей по ссылке лишь потому, что метод может менять их через скопированную ссылку
- ✗Ожидать, что метод сможет поменять местами две объектные переменные вызывающего переприсваиванием параметров
- ✗Думать, что в метод копируется сам объект, а не ссылка на него
Уточняющие вопросы
- →Почему метод может менять поля полученного объекта, но не может поменять местами два объекта вызывающего?
- →Чем передача массива отличается от передачи
intв тот же метод?
JuniorТеорияОчень частоВ чём разница между static-членом и instance-членом?
В чём разница между static-членом и instance-членом?
static-член принадлежит самому классу: есть одна общая копия для всех объектов, и доступ к нему идёт через класс без всякого экземпляра. Instance-член принадлежит каждому объекту, поэтому каждый объект получает свою отдельную копию. static-метод не может напрямую использовать поля экземпляра, потому что с вызовом не связан конкретный объект.
Типичные ошибки
- ✗Путать static (одна общая копия) с final (нельзя менять) — это независимые понятия
- ✗Думать, что каждый экземпляр получает свою копию static-поля, а не разделяет одну
- ✗Пытаться читать поля экземпляра прямо из static-метода без ссылки на объект
Уточняющие вопросы
- →Почему static-метод не может ссылаться на this, а метод экземпляра может?
- →Когда инициализируется static-поле относительно создания первого экземпляра?
MiddleТеорияОчень частоВ чём разница между final, finally и finalize?
В чём разница между final, finally и finalize?
Это три не связанные вещи. final — модификатор: final-переменная является константой, final-метод нельзя переопределить, а final-класс нельзя наследовать. finally — блок после try/catch, который выполняется всегда, даже если выброшено исключение, поэтому используется для очистки. finalize() — устаревший метод Object, который сборщик мусора мог вызвать перед освобождением объекта.
Типичные ошибки
- ✗Считать эти три связанными, хотя они отвечают за модификаторы, поток управления и сборку мусора по отдельности
- ✗Думать, что finally пропускается при выбросе исключения, хотя он выполняется в любом случае
- ✗Полагаться на finalize для очистки, хотя он устарел и может вообще не быть вызван
Уточняющие вопросы
- →Гарантированно ли выполнится блок finally, если try вызывает System.exit?
- →Почему finalize устарел, и что заменяет его для освобождения ресурсов?
JuniorТеорияЧастоЧто такое enum в Java и может ли он нести поля и методы?
Что такое enum в Java и может ли он нести поля и методы?
enum — это класс, экземпляры которого образуют фиксированный набор именованных констант, создаваемых JVM один раз, что делает его типобезопасным и пригодным для switch. Поскольку каждая константа — настоящий объект, enum может объявлять поля, приватный конструктор и методы, а отдельная константа даже переопределять метод собственным телом. Он неявно наследует java.lang.Enum, поэтому может реализовывать интерфейсы, но не может наследовать класс.
Типичные ошибки
- ✗Считать
enumголым спискомint-констант без собственного состояния и поведения - ✗Пытаться заставить
enumнаследовать класс, что невозможно, ведь он уже наследуетjava.lang.Enum - ✗Создавать константу через
newвместо опоры на фиксированные экземпляры, которые JVM создаёт один раз
Уточняющие вопросы
- →Почему сравнение двух констант enum через
==безопасно, в отличие от сравнения двухInteger? - →Как
enumс одной константой бесплатно даёт singleton?
MiddleТеорияЧастоЧто такое varargs и во что их превращает компилятор?
Что такое varargs и во что их превращает компилятор?
Параметр varargs, записываемый как T... xs, позволяет передать любое число аргументов. Это сахар компилятора: параметр становится обычным массивом T[], а в точке вызова свободные аргументы заворачиваются в свежевыделенный массив, ссылка на который передаётся по значению. Внутри метода xs — просто массив, никогда не null, а при вызове без аргументов пустой. Он обязан быть последним параметром, и метод может объявить лишь один такой.
Типичные ошибки
- ✗Думать, что varargs отдают
List, а не обычный массив, созданный компилятором - ✗Ожидать, что вызов без аргументов передаст
null, а не пустой массив - ✗Считать, что метод может объявить больше одного параметра varargs или поставить его перед другим параметром
Уточняющие вопросы
- →Что именно получает varargs-метод, если его вызвали вообще без аргументов?
- →Почему передача готового
T[]в varargs-метод не выделяет второй массив?
JuniorТеорияИногдаКаково значение по умолчанию у поля и у локальной переменной?
Каково значение по умолчанию у поля и у локальной переменной?
Поля — и instance, и static — автоматически инициализируются значением по умолчанию для своего типа: 0 для числовых типов, false для boolean, '\u0000' для char и null для ссылок. Локальная переменная не получает никакого умолчания; компилятор требует определённого присваивания и отвергает любое чтение до того, как ей присвоено значение.
Типичные ошибки
- ✗Считать, что локальная переменная тихо обнуляется как поле, а не отвергается компилятором
- ✗Думать, что поле обязано быть явно инициализировано до использования, хотя оно получает умолчание автоматически
- ✗Полагать, что числовое поле по умолчанию равно
null, а не0
Уточняющие вопросы
- →Почему компилятор допускает неинициализированное поле, но не локальную переменную?
- →Какое умолчание получают элементы массива сразу после
new int[3]?
JuniorТеорияИногдаКакие ключевые черты определяют Java как язык?
Какие ключевые черты определяют Java как язык?
Java объектно-ориентированный, статически и строго типизированный язык. Исходный код компилируется в bytecode, который выполняет любая JVM, что делает его платформонезависимым (написал однажды — запускай везде). JVM управляет памятью автоматически через сборку мусора, поэтому здесь нет сырых указателей, и это повышает надёжность. Также есть встроенная поддержка многопоточности.
Типичные ошибки
- ✗Говорить, что Java компилируется в нативный машинный код, а не в переносимый bytecode для JVM
- ✗Называть Java динамически типизированным, хотя он статически типизирован и проверяется при компиляции
- ✗Утверждать, что Java требует ручного освобождения памяти вместо опоры на сборщик мусора
Уточняющие вопросы
- →Как JVM позволяет одному и тому же скомпилированному bytecode работать на разных ОС?
- →От чего сборка мусора освобождает программиста по сравнению с ручным управлением памятью?
JuniorТеорияИногдаВ каком порядке Java инициализирует поля и блоки?
В каком порядке Java инициализирует поля и блоки?
Статические части выполняются один раз при первой загрузке класса: сначала static-поля и static-блоки родителя, затем потомка, в порядке исходного кода. Затем на каждый экземпляр: родитель выполняет инициализаторы полей и instance-блоки и свой конструктор, затем то же делает потомок. То есть сначала весь static родителя, потом потомка; затем экземплярные части и конструктор родителя, потом потомка.
Типичные ошибки
- ✗Считать, что
static-блоки перевыполняются на каждое создание, а не один раз при загрузке класса - ✗Думать, что потомок инициализируется раньше родителя
- ✗Полагать, что конструктор выполняется раньше инициализаторов полей и instance-блоков
Уточняющие вопросы
- →Когда именно класс загружается и его
static-блок срабатывает? - →Почему чтение поля потомка из конструктора родителя может видеть значение по умолчанию?
JuniorТеорияИногдаПочему метод main объявлен как public static void main(String[] args)?
Почему метод main объявлен как public static void main(String[] args)?
Это точка входа JVM, поэтому JVM должна вызвать его до того, как существует какой-либо объект. public позволяет JVM вызвать его извне класса. static означает, что он запускается без создания экземпляра. void говорит, что он ничего не возвращает в JVM. String[] args принимает аргументы командной строки как массив строк.
Типичные ошибки
- ✗Думать, что JVM сначала создаёт экземпляр, вместо прямого вызова статического main
- ✗Считать, что main должен возвращать код выхода int, а не void
- ✗Полагать, что args хранит переменные окружения, а не аргументы командной строки
Уточняющие вопросы
- →Что произойдёт во время выполнения, если в классе нет метода с точной сигнатурой main?
- →Можно ли перегрузить main, и какую перегрузку JVM действительно вызывает?