Библиотека джависта | Java, Spring, Maven, Hibernate
24.8K subscribers
1.87K photos
38 videos
42 files
2.66K links
Все самое полезное для Java-разработчика в одном канале.

Список наших каналов: https://yangx.top/proglibrary/9197

Для обратной связи: @proglibrary_feeedback_bot

По рекламе: @proglib_adv

РКН: https://gosuslugi.ru/snet/67a5bbda1b17b35b6c1a55c4
加入频道
#вопросы_с_собеседований
Что такое busy spin?

busy spin – это техника, которую программисты используют, чтобы заставить поток ожидать при определённом условии. В отличие от традиционных методов wait(), sleep() или yield(), которые подразумевают уступку процессорного времени, этот метод вместо уступки выполняет пустой цикл. Это необходимо для того, чтобы сохранить кэш процессора, т.к. в многоядерных системах существует вероятность, что приостановленный поток продолжит своё выполнение уже на другом ядре, а это повлечет за собой перестройку состояния процессорного кэша, которая является достаточно затратной процедурой.
#вопросы_с_собеседований
Что такое «денормализация»? Для чего она применяется?

Денормализация базы данных
— это процесс осознанного приведения базы данных к виду, в котором она не будет соответствовать правилам нормализации. Обычно это необходимо для повышения производительности и скорости извлечения данных за счет увеличения избыточности данных.
#вопросы_с_собеседований
Как и когда происходит увеличение количества корзин в HashMap?

Помимо capacity у HashMap есть еще поле loadFactor, на основании которого, вычисляется предельное количество занятых корзин capacity * loadFactor. По умолчанию loadFactor = 0.75. По достижению предельного значения, число корзин увеличивается в 2 раза и для всех хранимых элементов вычисляется новое «местоположение» с учетом нового числа корзин.
#вопросы_с_собеседований
Объясните смысл параметров в конструкторе HashMap(int initialCapacity, float loadFactor).

initialCapacity - исходный размер HashMap, количество корзин в хэш-таблице в момент её создания.
loadFactor - коэффициент заполнения HashMap, при превышении которого происходит увеличение количества корзин и автоматическое перехэширование. Равен отношению числа уже хранимых элементов в таблице к её размеру.
#вопросы_с_собеседований
Сколько элементов будет пропущено, если Iterator.next() будет вызван после 10-ти вызовов Iterator.hasNext()?

Нисколько - hasNext() осуществляет только проверку наличия следующего элемента.
#вопросы_с_собеседований
Будет ли работать HashMap, если все добавляемые ключи будут иметь одинаковый hashCode()?

Да, будет, но в этом случае HashMap вырождается в связный список и теряет свои преимущества.
This media is not supported in your browser
VIEW IN TELEGRAM
Курс по алгоритмам и структурам данным начинается сегодня.
🚂 Запрыгиваем в уходящий поезд!

Информация для тех, кто еще думает:
• Разбираем все основные алгоритмы понятным языком;
• Тренируемся их применять и решаем задачи;
• Живые трансляции и общение в коммьюнити;
• Курс ведет разработчик Яндекс Go Степан Мацкевич;
• Ученики смогут пройти боевое тестовое собеседование с разработчиками Яндекс!

Вы сможете успеть сегодня отправить заявку и записаться в группу!

👉 Записывайтесь: https://proglib.io/w/a6bd553e
#вопросы_с_собеседований
Расскажите о методах жизненного цикла JSP.

Контейнер сервлетов (например, Tomcat, GlassFish) создает из JSP-страницы класс сервлета, наследующего свойства интерфейса javax.servlet.jsp.HttpJspBase и включающего следующие методы:
jspInit() — метод объявлен в JSP странице и реализуется с помощью контейнера. Этот метод вызывается один раз в жизненном цикле JSP для того, чтобы инициализировать конфигурационные параметры указанные в дескрипторе развертывания. Этот метод можно переопределить с помощью определения элемента JSP scripting и указания необходимых параметров для инициализации;
jspService() — метод переопределяется контейнером автоматически и соответствует непосредственно коду JSP, описанному на странице. Этот метод определен в интерфейсе HttpJspPage, его имя начинается с нижнего подчеркивания и он отличается от других методов жизненного цикла тем, что его невозможно переопределить;
jspDestroy() — метод вызывается контейнером для удаления объекта из памяти (на последней фазе жизненного цикла JSP - Destroy). Метод вызывается только один раз и доступен для переопределения, предоставляя возможность освободить ресурсы, которые были созданы в jspInit().
#вопросы_с_собеседований
В чём заключается разница между IO и NIO?

Java IO (input-output) является потокоориентированным, а Java NIO (new/non-blocking io) – буфер-ориентированным. Потокоориентированный ввод/вывод подразумевает чтение/запись из потока/в поток одного или нескольких байт в единицу времени поочередно. Данная информация нигде не кэшируются. Таким образом, невозможно произвольно двигаться по потоку данных вперед или назад. В Java NIO данные сначала считываются в буфер, что дает больше гибкости при обработке данных.
• Потоки ввода/вывода в Java IO являются блокирующими. Это значит, что когда в потоке выполнения вызывается read() или write() метод любого класса из пакета java.io.*, происходит блокировка до тех пор, пока данные не будут считаны или записаны. Поток выполнения в данный момент не может делать ничего другого. Неблокирующий режим Java NIO позволяет запрашивать считанные данные из канала (channel) и получать только то, что доступно на данный момент, или вообще ничего, если доступных данных пока нет. Вместо того, чтобы оставаться заблокированным пока данные не станут доступными для считывания, поток выполнения может заняться чем-то другим. Тоже самое справедливо и для неблокирующего вывода. Поток выполнения может запросить запись в канал некоторых данных, но не дожидаться при этом пока они не будут полностью записаны.
• В Java NIO имеются селекторы, которые позволяют одному потоку выполнения мониторить несколько каналов ввода. Т.е. существует возможность зарегистрировать несколько каналов с селектором, а потом использовать один поток выполнения для обслуживания каналов, имеющих доступные для обработки данные, или для выбора каналов, готовых для записи.
🦠 Планете угрожает страшный вирус, и только разработчики могут все исправить

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

Помогите Создателю и решите три задачи на языке Java или двух других. Каждая задача при этом разбита на блоки по грейдам. Кликайте на участок кода в задаче и выбирайте вариант его исправления. Успехов!

https://vk.cc/ceD1h5
#вопросы_с_собеседований
Расскажите про приведение типов. Что такое понижение и повышение типа?

Java является строго типизированным языком программирования, а это означает, то что каждое выражение и каждая переменная имеет строго определенный тип уже на момент компиляции. Однако определен механизм приведения типов (casting) - способ преобразования значения переменной одного типа в значение другого типа.

В Java существуют несколько разновидностей приведения:

Тождественное (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;
}
#вопросы_с_собеседований
Что такое «каналы»?

Каналы (channels)
– это логические (не физические) порталы, абстракции объектов более низкого уровня файловой системы (например, отображенные в памяти файлы и блокировки файлов), через которые осуществляется ввод/вывод данных, а буферы являются источниками или приёмниками этих переданных данных. При организации вывода, данные, которые необходимо отправить, помещаются в буфер, который затем передается в канал. При вводе, данные из канала помещаются в заранее предоставленный буфер.

Каналы напоминают трубопроводы, по которым эффективно транспортируются данные между буферами байтов и сущностями по ту сторону каналов. Каналы – это шлюзы, которые позволяют получить доступ к сервисам ввода/вывода операционной системы с минимальными накладными расходами, а буферы – внутренние конечные точки этих шлюзов, используемые для передачи и приема данных.
Чем синхронный сервер отличается от асинхронного?

Вопрос может быть сформулирован как «сравните Jetty и Netty», или «зачем нужен Spring WebFlux».

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

Таким образом, если каждый запрос выполняется одну секунду, то при всего лишь 2000 запросов в секунду сервер расходует 2000 потоков. Потоки в ОС – ограниченный ресурс, и не важно как сконфигурирован ваш сервер – в какой-то момент производительность резко просядет.

Альтернативное решение – асинхронные сервера. В них для потоков обработки HTTP-запросов используется work stealing. В широком смысле, вызовы асинхронных функций не блокируют выполнение, а их результат вместо return value возвращается параметром коллбэка. В Java этот результат зачастую возвращается в виде объекта Future.

Чтобы вся обработка запроса стала действительно асинхронной, необходимо также избавиться от блокирующих операций. Иначе преимущество подхода с work stealing выродится в простой пул потоков. Блокирующая работа с файлами и сетью должна быть заменена на NIO, а для БД должен быть использован асинхронный драйвер.
🔥 Бесплатный интенсив Java Concurrency пройдет с 8 по 10 июля

Три дня будем изучать многопоточность и закрепим знания на Live coding сессии, где вместе с Senior-разработчиком из Сбера напишем многопоточную программу.

После интенсива ты:

— Разберешься, в чем отличие между многопоточностью и параллельностью
— Научишься применять на практике средства для работы с многопоточностью, предоставляемые Java
— Сможешь проектировать многопоточные приложения, отлаживать, тестировать и оптимизировать их

Преподаватель:

👨🏼‍💻 Александр Литвинов — Team Lead в Сбере, 10 лет в разработке, преподаватель курса Middle Java Dev

🚀 Стартуем 8 июля в 19:00 мск

Регистрируйся бесплатно: https://cutt.ly/zKPaJGl
📊 «Сделай красиво и чтоб работало – это вместо ТЗ». Что больше всего раздражает программистов на работе? Результаты опроса «Библиотеки программиста»

Отправь эту статью коллеге или руководителю. Может что-нибудь поменяется.

https://proglib.io/sh/RHx4fjPaLT
#вопросы_с_собеседований
Какие некоторые из важных особенностей и преимуществ Spring Framework?

Spring Framework обеспечивает решения многих задач, с которыми сталкиваются Java-разработчики и организации, которые хотят создать информационную систему, основанную на платформе Java. Из-за широкой функциональности трудно определить наиболее значимые структурные элементы, из которых он состоит. Spring Framework не всецело связан с платформой Java Enterprise, несмотря на его масштабную интеграцию с ней, что является важной причиной его популярности.

Spring Framework, вероятно, наиболее известен как источник расширений (features), нужных для эффективной разработки сложных бизнес-приложений вне тяжеловесных программных моделей, которые исторически были доминирующими в промышленности. Ещё одно его достоинство в том, что он ввел ранее неиспользуемые функциональные возможности в сегодняшние господствующие методы разработки, даже вне платформы Java. Этот фреймворк предлагает последовательную модель и делает её применимой к большинству типов приложений, которые уже созданы на основе платформы Java. Считается, что Spring Framework реализует модель разработки, основанную на лучших стандартах индустрии, и делает её доступной во многих областях Java. Таким образом к достоинствам Spring можно отнести:

• Относительная легкость в изучении и применении фреймворка в разработке и поддержке приложения.
• Внедрение зависимостей (DI) и инверсия управления (IoC) позволяют писать независимые друг от друга компоненты, что дает преимущества в командной разработке, переносимости модулей и т.д..
Spring IoC контейнер управляет жизненным циклом Spring Bean и настраивается наподобие JNDI lookup (поиска).
• Проект Spring содержит в себе множество подпроектов, которые затрагивают важные части создания софта, такие как вебсервисы, веб программирование, работа с базами данных, загрузка файлов, обработка ошибок и многое другое. Всё это настраивается в едином формате и упрощает поддержку приложения.
#вопросы_с_собеседований
Какие подклассы класса InputStream вы знаете, для чего они предназначены?

InputStream - абстрактный класс, описывающий поток ввода;
BufferedInputStream - буферизованный входной поток;
ByteArrayInputStream позволяет использовать буфер в памяти (массив байтов) в качестве источника данных для входного потока;
DataInputStream - входной поток для байтовых данных, включающий методы для чтения стандартных типов данных Java;
FileInputStream - входной поток для чтения информации из файла;
FilterInputStream - абстрактный класс, предоставляющий интерфейс для классов-надстроек, которые добавляют к существующим потокам полезные свойства;
ObjectInputStream - входной поток для объектов;
StringBufferInputStream превращает строку (String) во входной поток данных InputStream;
PipedInputStream реализует понятие входного канала;
PushbackInputStream - разновидность буферизации, обеспечивающая чтение байта с последующим его возвратом в поток, позволяет «заглянуть» во входной поток и увидеть, что оттуда поступит в следующий момент, не извлекая информации.
SequenceInputStream используется для слияния двух или более потоков InputStream в единый.
#вопросы_с_собеседований
Для чего используется PushbackInputStream?

Разновидность буферизации, обеспечивающая чтение байта с последующим его возвратом в поток. Класс PushbackInputStream представляет механизм «заглянуть» во входной поток и увидеть, что оттуда поступит в следующий момент, не извлекая информации.

У класса есть дополнительный метод unread().
#вопросы_с_собеседований
Что вы понимаете под Dependency Injection (DI)?

Внедрение зависимости (Dependency injection, DI) — процесс предоставления внешней зависимости программному компоненту. Является специфичной формой «инверсии управления» ( Inversion of control, IoC), когда она применяется к управлению зависимостями. В полном соответствии с принципом единой обязанности объект отдаёт заботу о построении требуемых ему зависимостей внешнему, специально предназначенному для этого общему механизму. К достоинствам применения DI можно отнести:

• Сокращение объема связующего кода. Одним из самых больших плюсов DI является возможность значительного сокращения объема кода, который должен быть написан для связывания вместе различных компонентов приложения. Зачастую этот код очень прост — при создании зависимости должен создаваться новый экземпляр соответствующего объекта.
• Упрощенная конфигурация приложения. За счет применения DI процесс конфигурирования приложения значительно упрощается. Для конфигурирования классов, которые могут быть внедрены в другие классы, можно использовать аннотации или XML-файлы.
• Возможность управления общими зависимостями в единственном репозитории. При традиционном подходе к управлению зависимостями в общих службах, к которым относятся, например, подключение к источнику данных, транзакция, удаленные службы и т.п., вы создаете экземпляры (или получаете их из определенных фабричных классов) зависимостей там, где они нужны — внутри зависимого класса. Это приводит к распространению зависимостей по множеству классов в приложении, что может затруднить их изменение. В случае использования DI вся информация об общих зависимостях содержится в единственном репозитории (в Spring есть возможность хранить эту информацию в XML-файлах или Java классах), что существенно упрощает управление зависимостями и снижает количество возможных ошибок.
• Улучшенная возможность тестирования. Когда классы проектируются для DI, становится возможной простая замена зависимостей. Это особенно полезно при тестировании приложения.
• Стимулирование качественных проектных решений для приложений. Вообще говоря, проектирование для DI означает проектирование с использованием интерфейсов. Используя Spring, вы получаете в свое распоряжение целый ряд средств DI и можете сосредоточиться на построении логики приложения, а не на поддерживающей DI платформе.
#вопросы_с_собеседований
Что вы понимаете под аспектно-ориентированным программированием (Aspect Oriented Programming — AOP)?

Аспектно-ориентированное программирование (АОП) — это одна из “моделей программирования текущего момента” в мире Java. АОП предоставляет возможность реализации сквозной логики — т.е. логики, которая применяется к множеству частей приложения — в одном месте и обеспечения автоматического применения этой логики по всему приложению. Подход Spring к АОП заключается в создании “динамических прокси” для целевых объектов и “привязывании” объектов к конфигурированному совету для выполнения сквозной логики.