Уютное сообщество джавистов
2.02K subscribers
33 photos
43 links
Уютное сообщество джавистов - это хорошие материалы,задачки,
туториалы для проверки знаний и обратная связь от соратников по изучению.

@viktorreh
Download Telegram
Можно ли к блоку try-with-resources подключить блок finally?
Anonymous Quiz
62%
Да
15%
Нет
14%
Блока try-with-resources нет в Java
9%
Узнать ответ
Что такое «сервлет»?

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

Большинство необходимых для создания сервлетов классов и интерфейсов содержатся в пакетах javax.servlet и javax.servlet.http.

Основные методы сервлета:
public void init(ServletConfig config) throws ServletException запускается сразу после загрузки сервлета в память;
public ServletConfig getServletConfig() возвращает ссылку на объект, который предоставляет доступ к информации о конфигурации сервлета;
public String getServletInfo() возвращает строку, содержащую информацию о сервлете, например: автор и версия сервлета;
public void service(ServletRequest request, ServletResponse response) throws ServletException, java.io.IOException вызывается для обработки каждого запроса;
public void destroy() выполняется перед выгрузкой сервлета из памяти.
🔥2
VM Options

— это параметры, которые указываются при запуске JVM. В этом посте расскажу, чем они отличаются, и как безопасно перейти на новую версию java. В конце будет список самых популярных (и полезных) опций.

Все JVM опции делятся на три группы:

⚙️ Стандартные
Пишутся через минус и поддерживаются всеми JVM.
Пример: -classpath, -server, -version

⚙️ Нестандартные
Начинаются на -Х и определяют базовые свойства JVM. Могут не работать во всех JVM, но если поддерживаются, то вряд ли удалятся.
Пример: -Xmx, -Xms

⚙️ Продвинутые
Начинаются на -ХХ и касаются внутренних механизмов JVM. Не поддерживаются всеми JVM, часто меняются и удаляются.
Пример: -XX:MaxGCPauseMillis=500

Некоторые продвинутые опции требуют дополнительных флажков. Для экспериментальных фич обязателен -XX:+UnlockExperimentalVMOptions. Многие фичи диагностики не заработают без -XX:+UnlockDiagnosticVMOptions

Количество опций часто меняется. В 11 версии OpenJDK 1504 опции, а в 17 на 200 опций меньше.

Цикл отключения опций не совсем стандартный. В обычном коде что-то помечается Deprecated, и спустя время удаляется. VM Options используют более длинный цикл:

🔸 Deprecate: функционал работает, при запуске появляется warning
🔸 Obsolete: функция не выполняется, JVM пишет предупреждения
🔸 Expired: JVM не запускается

Многие опции очень нестабильны и часто меняются. Чтобы безопасно обновить версию java, нужно проверить набор опций через JaCoLine . Он подсветит устаревшие или уже бесполезные опции.

Полезные опции для java 11
(да, недавно вышла java 20, но самая популярная версия всё ещё 11)

1️⃣ Память

▫️ Начальный размер хипа: -Xms256m в абсолютных значениях, -XX:InitialRAMPercentage=60 - в процентах от RAM
▫️ Максимальный размер хипа: -Xmx8g или -XX:MaxRAMPercentage=60
▫️ Снять heap dump при переполнении памяти: -XX:+HeapDumpOnOutOfMemoryError. Адрес выходного файла задаётся в -XX:HeapDumpPath

2️⃣ Сборщик мусора

▫️ Serial GC: -XX:+UseSerialGC
▫️ Parallel GC: -XX:+UseParalllGC
▫️ CMS: -XX:+UseConcMarkSweepGC
▫️ G1: -XX:+UseG1GC (вариант по умолчанию)
▫️ ZGC: -XX:+UnlockExperimentalVMOptions -XX:+UseZGC
▫️ Shenandoah: -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC

Вывести статистику сборщика при завершении работы: -XX:+UnlockDiagnosticVMOptions ‑XX:NativeMemoryTracking=summary ‑XX:+PrintNMTStatistics

Базовое логгирование коллектора: -Xlog:gc
Максимально информативное: -Xlog:gc*

3️⃣ Посмотреть все доступные опции
⚙️ Нестандартные: java -X
⚙️ Продвинутые: java -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+PrintFlagsFinal
👍5
Приведите примеры структурных шаблонов проектирования.

Адаптер
(Adapter) — объект, обеспечивающий взаимодействие двух других объектов, один из которых использует, а другой предоставляет несовместимый с первым интерфейс.
Мост (Bridge) — структура, позволяющая изменять интерфейс обращения и интерфейс реализации класса независимо.
Компоновщик (Composite) — объект, который объединяет в себе объекты, подобные ему самому.
Декоратор (Decorator) — класс, расширяющий функциональность другого класса без использования наследования.
Фасад (Facade) — объект, который абстрагирует работу с несколькими классами, объединяя их в единое целое.
Приспособленец (Flyweight) — это объект, представляющий себя как уникальный экземпляр в разных местах программы, но по факту не являющийся таковым.
Заместитель (Proxy) — объект, который является посредником между двумя другими объектами, и который реализует/ограничивает доступ к объекту, к которому обращаются через него.

#вопросы_с_собеседований
👍41
Как написать компаратор

Компаратор задаёт правило сравнения элементов между собой. Делает он это с помощью метода compare:

public int compare(T o1, T o2) {…}

Если метод вернул
▫️ число больше нуля — первый элемент больше второго
▫️ 0 — элементы равны
▫️ число меньше нуля — первый меньше второго

Простейшая и популярная реализация — вычесть одно значение из другого:

(o1, o2) -> (int) (o1.getSum() - o2.getSum())

Что с этим не так?

Я всегда сомневаюсь, что из чего вычитать. Если вы отвечали на опрос дольше одной секунды, значит мы в одном лагере:) Компаратор — совсем не то место, где мозг должен спотыкаться.

В Java 8 в интерфейсе Comparator появился удобный метод:
orders.sort(comparing(Order::getSum))

Что классно:
Не надо вспоминать, что из чего вычитать
Легко сделать сравнение в обратном порядке:
comparing(Order::getSum).reversed()
Можно учесть null:
nullsFirst(comparing(Order::getSum))
nullLast(…)
Удобно сортировать по нескольким полям:
comparing(Order::getSum).thenComparing(Order::getId)

Самостоятельно обрабатывать null и писать сложные сортировки очень утомительно. Помню, как с удовольствием удаляла из проекта компараторы на 20 строк после перехода на Java 8😊

Важные нюансы:

1️⃣ comparing*

В интерфейсе Comparator также доступны методы comparingInt, comparingLong и comparingDouble. Используются для полей примитивного типа, чтобы избежать лишнего боксинга. Если в классе Order

Long id → используем comparing(Order::getId)
long id
comparingLong(Order::getId)

Не указывайте тип лишний раз. Для работы с объектами подойдёт обычный comparing

2️⃣ Нетривиальная работа с null*

В обычных методах легко понять, что происходит:
comparing(A).reversed().thenComparing(Б)
=
отсортировать по полю А в обратном порядке, дубликаты отсортировать по Б

Методы null* выбиваются из этой схемы.

nullsFirst(comparing(Order::getSum))

означает, что первыми будут null объекты, а существующие заказы отсортируются по сумме. Этот компаратор работает для такого кода:

orders.add(null); // эти элементы будут впереди
orders.add(new Order(…)); // эти отсортируются по полю sum

Если в списке нет null объектов, но в поле sum возможен null, придётся писать так:

…comparing(Order::getSum, nullsFirst(naturalOrder()));

Сравнение по нескольким nullable полям выглядит совсем плохо. К счастью, на практике такие задачи встречаются редко.

Ответ на вопрос перед постом:
(o1, o2) -> (int) (o2.getSum() - o1.getSum())

Но лучше использовать comparing(Order::getSum).reversed()
👍3😁1
Чем отличаются и что общего у InputStream, OutputStream, Reader, Writer?

☕️ InputStream и его наследники нужны для получения байтовых данных из разных источников
☕️
OutputStream и его наследники — набор классов, определяющих потоковый байтовый вывод
☕️
Writer и его наследники определяют потоковый вывод символов в юникоде
☕️
Reader и его наследники определяют потоковый ввод символов в юникоде

#вопросы_с_собеседований
👍6
Если ваше условие состоит в том, чтобы обе части сравнения были истинны, то какой оператор вы будете использовать?
Anonymous Quiz
2%
!
8%
||
87%
&&
1%
!=
3%
Узнать ответ
Инкапсуляция

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

Для достижения инкапсуляции в Java:
☕️ Объявите переменные класса как private.
☕️ Предоставьте public к методам установки и получения (сеттеру и геттеру) для изменения и просмотра значений переменных.

Преимущества инкапсуляции:
☕️ Поля класса можно сделать только для чтения или только для записи.
☕️ Класс может иметь полный контроль над тем, что хранится в его полях.
2👍2
Java 21: String templates

В сентябре выходит java 21 (LTS) с интересной превью фичей — String templates.

Есть две стратегии работы со строками:

🔸 Конкатенация — собираем строку по частям:

String str = "Hello, " + name + "!";

Сюда же относится StringBuilder, метод concat и тд.

🔸 Интерполяция — замена переменных внутри шаблона:

String name = "Jake";
String str = "Hello, ${name}!";

В чистом виде в java такого нет. В Formatter и MessageFormat вместо переменных какие-то %s и %d, а переменные стоят отдельно:

String.format("%d plus %d equals %d", x, y, x + y);

Для сравнения, как это выглядит в Kotlin:
"$x plus $y equals ${x + y}"

Так вот, в java 21 появится интерполяция!

В начале строки нужно добавить STR., а переменные поместить в \{}

int x = 10, y = 20;
String str = STR."\{x} + \{y} = \{x + y}";
// "10 + 20 = 30"

Хорошо работает вместе с текстовыми блоками (многострочные строки в тройных кавычках):

String name = "Joan";
String phone = "555-123";
String json = STR."""
{
"name": "\{name}",
"phone":"\{phone}",
}
""";

Внутри можно вызывать методы и писать блоки кода:

String time = STR."The time is \{
DateTimeFormatter
.ofPattern("HH:mm:ss")
.format(LocalTime.now())
} right now";
//"The time is 09:01:45 right now"

Читаемость текста снижается, но если очень хочется — почему нет.

Зачем нужен префикс STR? Почему нельзя просто добавить новый функционал в строки?

Здесь 2 причины:

1️⃣ Для обратной совместимости

На джаве написано много кода, и наверняка какие-то строки содержат блоки \{}. Будет обидно, если этот код перестанет компилироваться. Поэтому строки для интерполяции нужно явно обозначить

2️⃣ Может быть не только STR😱

Здесь открывается портал в другой мир. По задумке авторов темплейты могут подставлять переменные, валидировать данные и делать преобразования. Например, так:

JSONObject json = JSON."{ id: \{id}}";

или даже так:

ResultSet rs = DB."SELECT * FROM Person WHERE name = \{name}";

Для запросов в БД это, наверное, слишком, а вот для работы с JSON выглядит очень удобно.

Но рано радоваться🙂 Из коробки этого не будет, только набор классов для кастомизации. Будем надеяться, что авторы библиотек возьмут фичу на вооружение.

Как это работает? Выглядит как магия!

В JDK появится статическое поле StringProcessor STR, а строка

String str = STR."\{name}!";

во время компиляции превратится в

StringTemplate template = new StringTemplate(паттерн, параметры);
String str = STR.process(template)
;

Cинтаксический сахарок и никакого волшебства
👍101
Какой шаблон проектирования лежит в основе класса java.lang.StringBuffer?
Anonymous Quiz
9%
Abstract Factory
66%
Builder
8%
Facade
7%
Adapter
11%
Узнать ответ
👍1
Какое из этих слов не является ключевым в Java?
Anonymous Quiz
6%
static
12%
try
63%
String
9%
new
10%
Узнать ответ
Какие логические операции и операторы вы знаете?

• & : Логическое AND (И);
• && : Сокращённое AND;
• | : Логическое OR (ИЛИ);
• || : Сокращённое OR;
• ^ : Логическое XOR (исключающее OR (ИЛИ));
• ! : Логическое унарное NOT (НЕ);
• &= : AND с присваиванием;
• |= : OR с присваиванием;
• ^= : XOR с присваиванием;
• == : Равно;
• != : Не равно;
• ?: : Тернарный (троичный) условный оператор.

#вопросы_с_собеседований
Сортировка списка и костыль в JDK

Вести абстрактные разговоры о разработке легко и приятно. Можно два часа рассуждать, что такое хорошее API, но гораздо полезнее обсудить конкретные примеры. Сегодня разберём метод сортировки.

Если показать вопрос перед постом питонисту, он однозначно выберет list.sort(). Хотя бы потому что в питоне есть такой метод.

Класс Integer реализует интерфейс Comparable, сортировка чисел — базовая функциональность любого языка программирования. Так что метод sort() максимально логичен.

Однако в интерфейсе List нет такого метода, только
void sort(Comparator<? super E> c) {…}

Для элементарной операции сортировки чисел приходится писать
list.sort(Comparator.naturalOrder())

Код с Comparator.naturalOrder() похож на какой-то костыль. Под капотом не происходит ничего особенного, реализация компаратора очень простая:
(с1, с2) -> c1.compareTo(c2)

Так зачем писать так сложно? Почему в интерфейсе List нет метода sort()?

Сейчас расскажу:)

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

C начала 2000-х в JDK есть метод Collections.sort(List). Статический метод, который меняет внутреннее состояние аргумента. Сейчас это порицается, но в те времена было норм.

В больших компаниях классы JDK часто расширяли удобными методами, в том числе сортировкой в функциональном стиле:
CustomList sorted = list.sort();

Спустя много лет стало понятно, что экземплярные методы сортировки — это классно, и надо добавить такой метод в JDK. Чтобы текущие реализации списков не сломались, это должен быть дефолтный метод в интерфейсе List.

Но есть проблема. Допустим, на проекте есть такой класс:
public class CustomList implements List {
public CustomList sort() {…}
}

Допустим, в java 8 в интерфейс List добавили метод
default void sort() {…}

Старый метод не может переопределить дефолтный. тк возвращаемые значения не совместимы. Поэтому проекты, которые определили свой функциональный sort в начале 2000-х, перестанут компилироваться. Пользователи будут недовольны.

Многие проекты полагаются на свой sort, поэтому разработчики JDK не стали добавлять его в интерфейс. Метод sort(Comparator) использовался редко, поэтому теперь он с нами.

У Stream API нет проблем с совместимостью, так что для стримов есть прекрасный метод sorted(). Для коллекций метод sorted() есть в Kotlin💖
(обратите внимание на суффикс -ed, всё по правилам функционального подхода)

Ответ на вопрос перед постом: отсортировать список можно так:
list.sort(Comparator.naturalOrder());
list = list.stream().sorted().toList();

Если вам понравился list.sort(), значит у вас хороший вкус на API. К сожалению, у java свои загоны, поэтому этого метода в JDK нет.
👍62
Какая строка первой вызовет ошибку компиляции?
Anonymous Quiz
33%
l1
9%
l2
9%
l3
17%
l4
32%
Узнать ответ
Уютное сообщество джавистов
Photo
Ошибка, не прислали само условие. 7% правильно ответило) 41% почти)
🤣3
Сколько переходов происходит в момент вызова HashMap.get(key) по ключу, который есть в таблице?

• ключ равен null: 1 - выполняется единственный метод getForNullKey().

• любой ключ отличный от null: 4 - вычисление хэш-кода ключа; определение номера корзины; поиск значения; возврат значения.

#вопросы_с_собеседований
👍3
Какой из этих конструкторов используется для создания пустого объекта String?
Anonymous Quiz
63%
String()
4%
String(void)
3%
String(0)
30%
Ни один из перечисленных
Метод Character.toString()

Метод Character.toString() используется для преобразования символа (char) в строку (String).

Метод принадлежит классу Character и полезен, когда нужно конвертировать символ в строку для вывода или конкатенации.
👍2