➡️ Maven
Maven — один из трёх самых популярных инструментов для сборки проектов на Java. Он отвечает за компиляцию, создание jar-файлов (Java-архивов), создание дистрибутива программы, генерацию документации.
🗣️ Maven — просто отличная штука, хоть поначалу и не очень понятная. Если вы никогда не использовали Maven раньше, вы многое потеряли.
🔗 Ссылочка на доку
Java Learning 👩💻
Походу кому-то такое выражение больше по душе)
Читать полностью…
⚙️ Метод forEach()
Java 8 добавила метод forEach() в интерфейс java.lang.Iterable, что упрощает работу с коллекциями и повышает читаемость кода.
✔️ Вместо создания и использования Iterator можно использовать forEach() для обхода элементов.
Java Learning 👩💻
Я вот тоже про это подумал
С каких это пор использование вложенного try/catch стало хорошей практикой 🤮
➡️ Закрытие потоков в собственном блоке try
Раньше я закрывал потоки InputStream и OutputStream следующим образом:
InputStream is = null;
OutputStream os = null;
try {
is = new FileInputStream("application.json");
os = new FileOutputStream("application.log");
} catch (IOException io) {
// Обработка исключения
} finally {
is.close();
os.close();
}
InputStream is = null;
OutputStream os = null;
try {
is = new FileInputStream("../input/fxrates.txt");
os = new FileOutputStream("../output/fxrates.txt");
......
} finally {
try { if (is != null) is.close(); } catch(IOException e) {//closing quietly}
try { if (os != null) os.close(); } catch(IOException e) {//closing quietly}
}
get для одного элемента - O(n)
get для каждого элемента (которых n) - O(n^2)
👍 Тест по Java
Проверь насколько хорошо ты знаешь Java и готов освоить Spring!
Ответишь — пройдешь на продвинутый курс "Разработчик на Spring Framework" от OTUS по специальной цене.
👉 ПРОЙТИ ТЕСТ: https://clck.ru/3C6kTp
⏰ Время прохождения теста ограничено 30 минут, 21 вопрос.Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
А что насчёт расширенного/продвинутого for, он же foreach?
List<String> names = // ...Читать полностью…
for (String name : names)
// ...
⚡️ Узнайте, как манипулировать байт кодом Java-приложений!
На занятии разберем, как просматривать и читать байт код классов и для чего это может быть нужно. Научитесь создавать утилиты для изменения байт кода существующих классов в runtime. Это знание поможет вам улучшить производительность ваших приложений и решать сложные задачи.
Вебинар будет полезен Java-разработчикам, которые сталкиваются с вопросами производительности приложений.
Встречаемся 1 августа в 20:00 мск.
Спикер — Tech Lead в одном из крупнейших российских банков и кандидат технических наук.
👉 Регистрируйтесь прямо сейчас, чтобы посетить бесплатное занятие: https://clck.ru/3C5ZmHРеклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
➡️ Используйте интерфейсы, когда это возможно
Раньше я использовал конкретные классы, например ArrayList, Vector, и HashMap для возвращаемых значений и аргументов методов.
ℹ️ Это ограничивает гибкость. Вы не можете передать другой список, даже если он лучше, и при смене реализации нужно менять все места в коде.
✔️ Лучше использовать интерфейсы. Например, для упорядоченного списка с дубликатами используйте java.util.List, для неупорядоченного набора без дубликатов — java.util.Set, а для контейнера — Collection. Это позволит легко менять реализации.
Можно ещё больше упростить с помощью обобщений и extends. Например, вы можете использовать List<? extends Number>, что позволит передавать List<Integer> или List<Short>.
👀 Проверка состояния wait() в цикле
Когда я только начинал писать код для межпоточной коммуникации с использованием методов wait(), notify() и notifyAll(), я использовал if для проверки условия ожидания перед вызовом wait() и notify():
synchronized(queue) {
if(queue.isFull()){
queue.wait();
}
}🗣️ К счастью, проблем не возникло, но я понял свою ошибку, прочитав раздел из книги Effective Java. Там сказано, что условие ожидания следует проверять в цикле, потому что потоки могут получать ложные уведомления, и до того, как вы что-то сделаете, условие может снова стать истинным. Поэтому правильный способ использования wait() и notify() выглядит так:
synchronized(queue) {
while(queue.isFull()){
queue.wait();
}
}
⁉️ Kafka vs RabbitMQ — что выбрать?
Наш открытый урок — ваш шанс раз и навсегда понять, какая система лучше подходит для ваших задач.
Мы разберем ключевые различия между RabbitMQ и Apache Kafka, включая их архитектуру, производительность, способы хранения сообщений и внутреннюю организацию.
Вы увидите демонстрацию работы брокеров сообщений и получите сравнительный анализ, который поможет вам сделать осознанный выбор.
25 июля в 20:00 мск, ждем вас на открытом уроке, который пройдет в рамках онлайн-курса «Java Developer. Professional» в OTUS.
Занятие предназначено для разработчиков и архитекторов ПО.
👉 Записывайтесь на бесплатный вебинар «Kafka vs RabbitMQ: выбор правильной системы сообщений» прямо сейчас: https://otus.ru/lessons/java-professional/?utm_source=telegram&utm_medium=cpm&utm_campaign=java&utm_term=Java_per_month&utm_content=lesson_25-07-2025_usp-universal_java_text_no-headline_aida_short_aibanner_lesson-banner_blue_standart&erid=LjN8K78jd#event-4503
🎫 Начните обучение со скидкой в 10%, действует до конца июля.Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
⚙️ Использование Enum как Singleton
Жаль, что я не знал раньше, что можно написать Singleton в Java всего одной строкой:
public enum Singleton {
INSTANCE;
}• Потокобезопасность: Перечисления в Java создаются с использованием потокобезопасного механизма. Это означает, что вы не столкнетесь с проблемами, связанными с многопоточностью.• Гарантия единственности экземпляра: Java гарантирует, что в системе будет только один экземпляр перечисления, даже при использовании различных потоков или классов загрузчиков.• Сериализация и десериализация: При использовании enum Java автоматически обрабатывает сериализацию и десериализацию таким образом, чтобы сохранить единственность экземпляра. Это означает, что при десериализации вы не получите новый экземпляр, а вернется тот же самый экземпляр.
Блок finally выполняется всегда, даже если будет выброшено исключение. Так что пост неверный.
Читать полностью…
try(InputStream is = new FileInputStream("../input/fxrates.txt");Читать полностью…
OutputStream os = new FileOutputStream("../output/fxrates.txt")) {
......
}
👩💻 Курс для Java-разработчиков, которые хотят профессионального роста.
Пройди тест по Java и проверь свои знания, готов ли ты к обучению на курсе.
Ответишь — пройдешь на продвинутый курс "Java Developer. Professional" от OTUS по специальной цене + получишь доступ к записям открытых уроков курса курса
➡️ ПРОЙТИ ТЕСТ: https://clck.ru/3C7rwmРеклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
У меня другой вопрос. Почему get имеет O(n) для связанного списка? Если чуть выше показан квадрат записей, что правильно
Читать полностью…
⌛ Что будет выведено при выполнении кода?
Java Learning 👩💻
⚙️ Использование Dependency Injection в коде
Ранее я писал код следующим образом:
public class Game {
private HighScoreService service = HighScoreService.getInstance();
public void showLeaderBoard() {
List listOfTopPlayers = service.getLeaderBoard();
System.out.println(listOfTopPlayers);
}
}• Класс Game жестко связан с классом HighScoreService, что усложняет тестирование Game в изоляции.• Даже при наличии класса HighScoreService сложно протестировать Game, если HighScoreService делает сетевые запросы или загружает данные с серверов. Мок-объекты здесь не подходят.
Тоже норм. Под капотом тоже доступ через итератор.
Читать полностью…
➡️ Использование Iterator для перебора List
В Java есть несколько способов перебрать список: цикл for с индексом, расширенный for и Iterator. Раньше я использовал цикл for с методом get(), как показано ниже:
for (int i = 0; i < list.size(); i++) {
String name = list.get(i);
}🗣️ Этот метод работает для ArrayList, но если список — это LinkedList или другая реализация без поддержки случайного доступа, время выполнения увеличится до O(N^2), потому что get() для LinkedList имеет O(n) сложность.
Кроме того, при использовании циклов может возникнуть ошибка в многопоточном режиме, например, при работе с CopyOnWriteArrayList, когда один поток изменяет список, а другой пытается получить доступ к элементам, что может привести к IndexOutOfBoundsException.
Iterator<String> itr = list.iterator();
while (itr.hasNext()) {
String name = itr.next();
}
Ну так-то это ещё Джошуа Блох рекомендовал в своей шедевральной книге "Effective Java" - программируйте на уровне интерфейсов. Ничего нового.
Читать полностью…
➡️ Обработка CloneNotSupportedException и возврат экземпляра подкласса
Несмотря на критику функции клонирования объектов в Java, если вам нужно реализовать метод clone(), вот несколько лучших практик для упрощения задачи:
public Course clone() {
Course c = null;
try {
c = (Course)super.clone();
} catch (CloneNotSupportedException e) {} // Не произойдет
return c;
}clone() не вызовет CloneNotSupportedException, если класс реализует интерфейс Cloneable. Возврат подкласса называется ковариантным переопределением методов и доступен с Java 5, что позволяет избежать приведения типа на стороне клиента:Course javaBeginners = new Course("Java", 100, 10);
Course clone = javaBeginners.clone();clone():Date d = new Date();
Date clone = (Date) d.clone();
👀 Использование Arrays.asList() для инициализации коллекций или List.of(), Set.of()
Раньше, даже зная элементы заранее, я инициализировал коллекцию так:
List<String> listOfCurrencies = new ArrayList<>();
listOfCurrencies.add("USD/AUD");
listOfCurrencies.add("USD/JPY");
listOfCurrencies.add("USD/INR");
Arrays.asList() возвращает List, его нужно передать конструктору ArrayList, потому что возвращаемый список имеет фиксированную длину, и вы не можете добавлять или удалять элементы.List.of() и Set.of() для создания списка и множества с элементами. Это предпочтительнее, так как они возвращают неизменяемые списки и множества.
ℹ️ Использование entrySet для итерации по HashMap
Раньше я использовал keySet для итерации по HashMap, как показано ниже:
Set<Key> keySet = map.keySet();
for (Key k : keySet) {
Value v = map.get(k);
print(k, v);
}
Set<Map.Entry<Key, Value>> entrySet = map.entrySet();
for (Map.Entry<Key, Value> e : entrySet) {
Key k = e.getKey();
Value v = e.getValue();
}