Имеет ли смысл объявлять метод private final?
Объявление метода с модификаторами private и final имеет смысл, когда вы хотите:
— Скрыть детали реализации метода от других классов.
— Зафиксировать определенное поведение метода и не дать его переопределить.
— Сделать метод доступным только для использования внутри данного класса.
#вопросы_с_собеседований
— Скрыть детали реализации метода от других классов.
— Зафиксировать определенное поведение метода и не дать его переопределить.
— Сделать метод доступным только для использования внутри данного класса.
👎14👍2
Что означает переопределение метода в Java (override)?
Anonymous Quiz
78%
Изменение поведения метода относительно родительского
5%
Изменение поведения метода относительно дочернего
17%
Несколько методов с одинаковыми названиями, но разными наборами параметров
👍1
Что произойдет при вызове Iterator.next() без предварительного вызова Iterator.hasNext()?
Если итератор указывает на последний элемент коллекции, то возникнет исключение NoSuchElementException, иначе будет возвращен следующий элемент.
#вопросы_с_собеседований
Какое значение будет сохранено в строку s? String s = "value = " + 2 + 2;
Anonymous Quiz
9%
"value = 2 + 2"
43%
"value = 22"
19%
Compiler Error
23%
"value = 4"
7%
"value = 2 2"
В чем разница между Iterator и Enumeration?
— Iterator появился в JDK 1.2 и реализует интерфейс Iterable, в то время как Enumeration существовал в более ранних версиях JDK и не реализует Iterable.
— Методы Iterator позволяют удалять элементы во время итерации, в то время как методы Enumeration не предоставляют такой возможности.
— Iterator является "fail-fast", то есть выбросит ConcurrentModificationException, если коллекция была изменена, а Enumeration не гарантирует такого поведения.
— Iterator поддерживает обобщенные типы, а Enumeration работает только с объектами типа Object.
#вопросы_с_собеседований
— Методы Iterator позволяют удалять элементы во время итерации, в то время как методы Enumeration не предоставляют такой возможности.
— Iterator является "fail-fast", то есть выбросит ConcurrentModificationException, если коллекция была изменена, а Enumeration не гарантирует такого поведения.
— Iterator поддерживает обобщенные типы, а Enumeration работает только с объектами типа Object.
👍5
Что будет выведено на экран в результате выполнения следующего кода: public class SomeClass { static int x = 5; public static void main(String[] args) { int x; int y = 5; if (y > 3) x = 1; System.out.println(x); } }
Anonymous Quiz
28%
Compiler error
51%
1
3%
3
9%
Error warning
9%
5
В каком случае использование TreeSet предпочтительнее использования HashSet?
Anonymous Quiz
9%
Когда необходимо часто осуществлять обращение к элементам из Set
12%
Когда необходимо часто вставлять в Set новые элементы или удалять их
70%
Когда нужно гарантировать сохранение порядка элементов коллекции
9%
Когда нужно модифицировать производительность итератора по коллекции
Как происходит удаление элементов из ArrayList? Как меняется в этом случае размер ArrayList?
При удалении произвольного элемента из списка, все элементы, находящиеся «правее» смещаются на одну ячейку влево и реальный размер массива (его емкость, capacity) не изменяется никак.
Механизм автоматического «расширения» массива существует, а вот автоматического «сжатия» нет, можно только явно выполнить «сжатие» командой trimToSize().
#вопросы_с_собеседований
Механизм автоматического «расширения» массива существует, а вот автоматического «сжатия» нет, можно только явно выполнить «сжатие» командой trimToSize().
Предположим, что класс В наследует класс А. Какое утверждение обязательно верно?
Anonymous Quiz
14%
Если класс А имеет только private конструкторы, то и конструкторы класса B должны быть private
44%
Если класс А имел статический метод, то метод в классе В с той же сигнатурой тоже должен быть статик
9%
Если А абстрактный, то класс В тоже должен быть
5%
Если А объявлен final, то класс В тоже должен быть
28%
Если А объявлен public, то класс В тоже должен быть
❤6😁1
Как и когда происходит увеличение количества корзин в HashMap?
Помимо capacity у HashMap есть еще поле loadFactor, на основании которого, вычисляется предельное количество занятых корзин capacity * loadFactor. По умолчанию loadFactor = 0.75. По достижению предельного значения, число корзин увеличивается в 2 раза и для всех хранимых элементов вычисляется новое «местоположение» с учетом нового числа корзин.
#вопросы_с_собеседований
#вопросы_с_собеседований
👍5👎1
В чем заключается особенность работы метода clone () с полями объекта типа ссылки?
При клонировании объектов копируются только примитивные значения и значение ссылок на объекты. Это значит, что если объект имеет во внутреннем поле ссылку на другой объект, то будет клонирована только эта ссылка, сам же этот другой объект клонирован не будет. Собственно, это и называют — поверхностным клонированием.
Ну а что, если вам нужно полноценное клонирование с клонированием всех вложенных объектов? Как сделать, чтобы это были не копии ссылок, а полноценные клоны объекты с другими занимаемыми ячейками памяти в куче?
На самом деле все довольно просто — для этого вам нужно в каждом классе этих внутренних объектов также переопределить метод clone() и добавить интерфейс маркер — Cloneable. Тогда будут скопированные не ссылки на объекты, а сами объекты, ведь теперь они тоже имеют возможность копировать себя.
#вопросы_с_собеседований
Ну а что, если вам нужно полноценное клонирование с клонированием всех вложенных объектов? Как сделать, чтобы это были не копии ссылок, а полноценные клоны объекты с другими занимаемыми ячейками памяти в куче?
На самом деле все довольно просто — для этого вам нужно в каждом классе этих внутренних объектов также переопределить метод clone() и добавить интерфейс маркер — Cloneable. Тогда будут скопированные не ссылки на объекты, а сами объекты, ведь теперь они тоже имеют возможность копировать себя.
❤5👍2🎉2
В чем заключается особенность работы метода clone () с полями объекта типа ссылки?
При клонировании объектов копируются только примитивные значения и значение ссылок на объекты. Это значит, что если объект имеет во внутреннем поле ссылку на другой объект, то будет клонирована только эта ссылка, сам же этот другой объект клонирован не будет. Собственно, это и называют — поверхностным клонированием.
Ну а что, если вам нужно полноценное клонирование с клонированием всех вложенных объектов? Как сделать, чтобы это были не копии ссылок, а полноценные клоны объекты с другими занимаемыми ячейками памяти в куче?
На самом деле все довольно просто — для этого вам нужно в каждом классе этих внутренних объектов также переопределить метод clone() и добавить интерфейс маркер — Cloneable. Тогда будут скопированные не ссылки на объекты, а сами объекты, ведь теперь они тоже имеют возможность копировать себя.
#вопросы_с_собеседований
Ну а что, если вам нужно полноценное клонирование с клонированием всех вложенных объектов? Как сделать, чтобы это были не копии ссылок, а полноценные клоны объекты с другими занимаемыми ячейками памяти в куче?
На самом деле все довольно просто — для этого вам нужно в каждом классе этих внутренних объектов также переопределить метод clone() и добавить интерфейс маркер — Cloneable. Тогда будут скопированные не ссылки на объекты, а сами объекты, ведь теперь они тоже имеют возможность копировать себя.
🔥5
Приведите примеры структурных шаблонов проектирования.
Адаптер (Adapter) — объект, обеспечивающий взаимодействие двух других объектов, один из которых использует, а другой предоставляет несовместимый с первым интерфейс.
Мост (Bridge) — структура, позволяющая изменять интерфейс обращения и интерфейс реализации класса независимо.
Компоновщик (Composite) — объект, который объединяет в себе объекты, подобные ему самому.
Декоратор (Decorator) — класс, расширяющий функциональность другого класса без использования наследования.
Фасад (Facade) — объект, который абстрагирует работу с несколькими классами, объединяя их в единое целое.
Приспособленец (Flyweight) — это объект, представляющий себя как уникальный экземпляр в разных местах программы, но по факту не являющийся таковым.
Заместитель (Proxy) — объект, который является посредником между двумя другими объектами, и который реализует/ограничивает доступ к объекту, к которому обращаются через него.
#вопросы_с_собеседований
Мост (Bridge) — структура, позволяющая изменять интерфейс обращения и интерфейс реализации класса независимо.
Компоновщик (Composite) — объект, который объединяет в себе объекты, подобные ему самому.
Декоратор (Decorator) — класс, расширяющий функциональность другого класса без использования наследования.
Фасад (Facade) — объект, который абстрагирует работу с несколькими классами, объединяя их в единое целое.
Приспособленец (Flyweight) — это объект, представляющий себя как уникальный экземпляр в разных местах программы, но по факту не являющийся таковым.
Заместитель (Proxy) — объект, который является посредником между двумя другими объектами, и который реализует/ограничивает доступ к объекту, к которому обращаются через него.
#вопросы_с_собеседований
👍7🔥1😁1
«Я вообще нифига не понимаю. И скоро это поймут»: умелец устроился на работу Senior java-разработчиком на ₽300,000 сразу после курсов.
Он наврал в резюме, а теперь ищет спеца, на которого скинет всю работу за 50% от зарплаты.
Ждем курса от умельца, как устроиться Senior разработчиком без навыков и опыта.
Он наврал в резюме, а теперь ищет спеца, на которого скинет всю работу за 50% от зарплаты.
Ждем курса от умельца, как устроиться Senior разработчиком без навыков и опыта.
🥱5👍2
Выполнится ли до конца задача, отправленная в экзекьютор? Длительность задачи - около 500мс
#полезное
#полезное
👍1
Выполнится ли до конца задача, отправленная в экзекьютор?
Длительность задачи - около 500мс
Длительность задачи - около 500мс
Anonymous Poll
38%
Да, если она начала выполнение до вызова cancel
13%
Нет
50%
Невозможно определить
😁1
Best practice: не использовать boolean параметры в методах
На вопрос выше сходу ответят только знатоки многопоточки. Остальные наверняка попытались придумать, что означает
Метод
Public методы определяют интерфейс. В хорошем API пользователю не нужно зарываться в доки, чтобы понять, как пользоваться классом.
Даже если у параметров хорошие имена, итоговые true и false выглядят несимпатично и неудобно.
С private методами ситуация другая. Внутренняя реализация должна быть читаемой и понятной, но требования всё же менее жёсткие, чем у public методов. В private методах флажки допустимы, но увлекаться не стоит:)
Как исправить метод с boolean параметром?
1️⃣ Сделать два метода
и зашить "особенность" флажка в название. Необязательно дублировать реализацию — public методы могут под капотом вызывать private метод с флажком.
Так сделано, например, в классе
2️⃣ Создать enum с двумя значениями и передавать его вместо флажка
Такой вариант предлагается в книге Effective Java (Item 51).
Выглядит лучше, чем флажки, но на практике такой способ встречается редко. Если enum нужен только для обозначения true/false, быстрее и проще сделать 2 метода с разными именами.
🔥 Ответ на вопрос перед постом — "невозможно определить".
Мы не знаем точно, начала ли задача выполнение до вызова cancel. Даже если задача стартовала, успех cancel зависит от кода внутри задачи. Поэтому итог непредсказуем🤷♀️
#полезное
На вопрос выше сходу ответят только знатоки многопоточки. Остальные наверняка попытались придумать, что означает
cancel(true)
, и в чём разница с cancel(false)
.Метод
Future#cancel
— наглядная иллюстрация, почему boolean параметры в public методах не ок. Потому что непонятно, что означают true и false.Public методы определяют интерфейс. В хорошем API пользователю не нужно зарываться в доки, чтобы понять, как пользоваться классом.
Даже если у параметров хорошие имена, итоговые true и false выглядят несимпатично и неудобно.
С private методами ситуация другая. Внутренняя реализация должна быть читаемой и понятной, но требования всё же менее жёсткие, чем у public методов. В private методах флажки допустимы, но увлекаться не стоит:)
Как исправить метод с boolean параметром?
1️⃣ Сделать два метода
и зашить "особенность" флажка в название. Необязательно дублировать реализацию — public методы могут под капотом вызывать private метод с флажком.
Так сделано, например, в классе
HashMap
для методов put(k,v)
и putIfAbsent(k,v)
. Оба в итоге вызывают private метод putVal
с флажком ifAbsent2️⃣ Создать enum с двумя значениями и передавать его вместо флажка
enum ReplicateStatus {NO_REPLICATION, REPLICATE};
...
saveRequest(req, ReplicateStatus.REPLICATE);
Такой вариант предлагается в книге Effective Java (Item 51).
Выглядит лучше, чем флажки, но на практике такой способ встречается редко. Если enum нужен только для обозначения true/false, быстрее и проще сделать 2 метода с разными именами.
🔥 Ответ на вопрос перед постом — "невозможно определить".
Мы не знаем точно, начала ли задача выполнение до вызова cancel. Даже если задача стартовала, успех cancel зависит от кода внутри задачи. Поэтому итог непредсказуем🤷♀️
#полезное
👍5⚡1
IDEA: как не потерять важные места в коде
В огромном проекте всегда есть места, которые хочется отметить или быстро находить.
Раньше это делали так:
🔴 Ставили неактивный брейкпойнт в нужном месте. В принципе нормально, но иногда сложно вспомнить, что где находится
⭐️ Добавляли файл в favorites. Файл добавляется целиком, что не очень удобно
Затем в IDEA убрали favorites и добавили закладки. Супер удобно, ни одна важная строчка теперь не потеряется.
▫️ Курсор на нужной строке → F11 → появляется закладка
▫️ Правый щёлк по закладке → Rename bookmark… → ввести что-то осмысленное
▫️ Посмотреть закладки: View → Tool Windows → Bookmarks (или Shift + F11)
В огромном проекте всегда есть места, которые хочется отметить или быстро находить.
Раньше это делали так:
🔴 Ставили неактивный брейкпойнт в нужном месте. В принципе нормально, но иногда сложно вспомнить, что где находится
⭐️ Добавляли файл в favorites. Файл добавляется целиком, что не очень удобно
Затем в IDEA убрали favorites и добавили закладки. Супер удобно, ни одна важная строчка теперь не потеряется.
▫️ Курсор на нужной строке → F11 → появляется закладка
▫️ Правый щёлк по закладке → Rename bookmark… → ввести что-то осмысленное
▫️ Посмотреть закладки: View → Tool Windows → Bookmarks (или Shift + F11)
👍3❤2
8 ошибок начинающих разработчиков
Рассмотрим типичную историю начинающего разработчика👶
Чтобы стать программистом, он долго учился. Прошёл много курсов, писал учебные проекты. У них маленькая кодовая база, один пользователь, а главная задача — отработать алгоритм или попробовать фреймворк.
В этих условиях у стажёра сформировался стиль написания кода.
После собеседования стажёр начинает работать в крупном проекте вместе с другими разработчиками. И здесь очень важно перестроиться: многие паттерны, нормальные в учебных проектах, уже не подходят.
В этом посте опишу 8 таких паттернов на простых примерах.
1️⃣ Процедурный стиль
Задача: получить список заказов пользователя. Новичок скорее всего напишет такой код:
Во входной параметр
В системах со сложной бизнес-логикой такой подход усложняет чтение, тестирование и возможную параллелизацию.
Как лучше: использовать выходные параметры, не менять входные данные, давать осмысленные имена методам:
2️⃣ Сложные универсальные методы
Задача: по-разному считать скидку для новых пользователей и пользователей с картами лояльности.
Новички часто используют принцип Don't Repeat Yourself на максималках и пишут универсальный метод с кучей параметров и десятком if внутри:
Как лучше: сфокусированные методы для разных ситуаций
3️⃣ Длинные методы
Сложно читать и тестировать, страшно менять.
4️⃣ Любовь к статическим методам
Как лучше: небольшие методы, связанные с конкретным классом. Связность ниже, ошибок меньше.
5️⃣ Сложное проектирование
Задача: завести три типа пользователей: новые, обычные и VIP. Новички скорее всего сделают интерфейс, 3 класса и статический класс с фабричными методами и билдером.
Как лучше: как можно проще. Например, один класс пользователя с полем Тип. Усложнять при реальной необходимости
PS Все "как лучше" не всегда лучше. Но думаю, идея понятна.
6️⃣ Нулевое или минимальное покрытие тестами
как следствие больших сложных методов и недостаточной инкапсуляции.
7️⃣ Низкий уровень ответственности
Пункт не относится к разработке, но очень актуален для начинающих. Проявляется в двух формах:
🔸 Непонятно, что происходит. Человек сидит и молчит до последнего, пока не спросишь статус задачи или про возможные трудности. Он умалчивает проблемы или переносит на других:
— Что с задачей, которую я тебе дала 3 дня назад?
— Я не понял, куда смотреть, потом меня HR позвал бумаги подписывать, потом я настраивал гит, увидел другую задачу и переключился на неё.
🔸 Код не решает проблему, а заметает симптомы:
— Приходил пустой параметр, и я выставил дефолтный. Тесты мешали сделать пул-реквест, и я их отключил.
8️⃣ Слабые коммуникативные навыки
— Как ты починил баг с расчётом ставки?
— Там через геттер фабричный метод нашёл, и потом докер с постгрёй поднял посмотреть, в логах был фильтр урезанный, я письмо отправил тебе в цц, но вроде скоуп не тот или тот, короче, запушил
— В чём была ошибка?
— Там два двоеточия вылезло
— Где?
— В дебаге
— 🤯
Эти ошибки ожидаемы в начале работы, я тоже их совершала🙂 Чем быстрее вы перестроитесь на командный стиль разработки, тем вероятнее пройдёте испытательный срок и быстрее вольётесь в проект.
#полезное
Рассмотрим типичную историю начинающего разработчика👶
Чтобы стать программистом, он долго учился. Прошёл много курсов, писал учебные проекты. У них маленькая кодовая база, один пользователь, а главная задача — отработать алгоритм или попробовать фреймворк.
В этих условиях у стажёра сформировался стиль написания кода.
После собеседования стажёр начинает работать в крупном проекте вместе с другими разработчиками. И здесь очень важно перестроиться: многие паттерны, нормальные в учебных проектах, уже не подходят.
В этом посте опишу 8 таких паттернов на простых примерах.
1️⃣ Процедурный стиль
Задача: получить список заказов пользователя. Новичок скорее всего напишет такой код:
List list = new ArrayList();
process(user, list);
Во входной параметр
list
потом запишется результат. Такой стиль часто идёт из учебных заданий по алгоритмам, где экономится каждый бит и максимально сокращается количество объектов.В системах со сложной бизнес-логикой такой подход усложняет чтение, тестирование и возможную параллелизацию.
Как лучше: использовать выходные параметры, не менять входные данные, давать осмысленные имена методам:
List orders = getOrders(user);
2️⃣ Сложные универсальные методы
Задача: по-разному считать скидку для новых пользователей и пользователей с картами лояльности.
Новички часто используют принцип Don't Repeat Yourself на максималках и пишут универсальный метод с кучей параметров и десятком if внутри:
getDiscount(user, true, true, limit, true)
Как лучше: сфокусированные методы для разных ситуаций
getDiscountNew(user);
getDiscountLoyal(user, limit)
3️⃣ Длинные методы
Сложно читать и тестировать, страшно менять.
4️⃣ Любовь к статическим методам
Как лучше: небольшие методы, связанные с конкретным классом. Связность ниже, ошибок меньше.
5️⃣ Сложное проектирование
Задача: завести три типа пользователей: новые, обычные и VIP. Новички скорее всего сделают интерфейс, 3 класса и статический класс с фабричными методами и билдером.
Как лучше: как можно проще. Например, один класс пользователя с полем Тип. Усложнять при реальной необходимости
PS Все "как лучше" не всегда лучше. Но думаю, идея понятна.
6️⃣ Нулевое или минимальное покрытие тестами
как следствие больших сложных методов и недостаточной инкапсуляции.
7️⃣ Низкий уровень ответственности
Пункт не относится к разработке, но очень актуален для начинающих. Проявляется в двух формах:
🔸 Непонятно, что происходит. Человек сидит и молчит до последнего, пока не спросишь статус задачи или про возможные трудности. Он умалчивает проблемы или переносит на других:
— Что с задачей, которую я тебе дала 3 дня назад?
— Я не понял, куда смотреть, потом меня HR позвал бумаги подписывать, потом я настраивал гит, увидел другую задачу и переключился на неё.
🔸 Код не решает проблему, а заметает симптомы:
— Приходил пустой параметр, и я выставил дефолтный. Тесты мешали сделать пул-реквест, и я их отключил.
8️⃣ Слабые коммуникативные навыки
— Как ты починил баг с расчётом ставки?
— Там через геттер фабричный метод нашёл, и потом докер с постгрёй поднял посмотреть, в логах был фильтр урезанный, я письмо отправил тебе в цц, но вроде скоуп не тот или тот, короче, запушил
— В чём была ошибка?
— Там два двоеточия вылезло
— Где?
— В дебаге
— 🤯
Эти ошибки ожидаемы в начале работы, я тоже их совершала🙂 Чем быстрее вы перестроитесь на командный стиль разработки, тем вероятнее пройдёте испытательный срок и быстрее вольётесь в проект.
#полезное
👍2