microJUG
رفتن به کانال در Telegram
Мысли о Java. Основной канал: @miniJUG Буст: https://t.me/microJUG?boost Чат: https://t.me/micro_JUG Таблица JEP'ов: https://minijug.org/jeps.html
نمایش بیشتر803
مشترکین
اطلاعاتی وجود ندارد24 ساعت
اطلاعاتی وجود ندارد7 روز
اطلاعاتی وجود ندارد30 روز
در حال بارگیری داده...
کانالهای مشابه
ابر برچسبها
هیچ دادهای
مشکلی وجود دارد؟ لطفاً صفحه را تازه کنید یا با مدیر پشتیبانی ما تماس بگیرید.
اشارات ورودی و خروجی
---
---
---
---
---
---
جذب مشترکین
دسامبر '24
دسامبر '24
+10
در 0 کانالها
نوامبر '24
+10
در 0 کانالها
Get PRO
اکتبر '24
+28
در 0 کانالها
Get PRO
سپتامبر '24
+22
در 0 کانالها
Get PRO
اوت '24
+3
در 0 کانالها
Get PRO
ژوئیه '24
+14
در 0 کانالها
Get PRO
ژوئن '24
+9
در 0 کانالها
Get PRO
مه '24
+11
در 0 کانالها
Get PRO
آوریل '24
+23
در 0 کانالها
Get PRO
مارس '24
+54
در 0 کانالها
Get PRO
فوریه '24
+14
در 0 کانالها
Get PRO
ژانویه '24
+25
در 0 کانالها
Get PRO
دسامبر '23
+60
در 1 کانالها
Get PRO
نوامبر '23
+28
در 0 کانالها
Get PRO
اکتبر '23
+11
در 0 کانالها
Get PRO
سپتامبر '23
+17
در 0 کانالها
Get PRO
اوت '23
+4
در 0 کانالها
Get PRO
ژوئیه '23
+24
در 0 کانالها
Get PRO
ژوئن '23
+20
در 0 کانالها
Get PRO
مه '23
+5
در 0 کانالها
Get PRO
آوریل '23
+5
در 0 کانالها
Get PRO
مارس '23
+21
در 0 کانالها
Get PRO
فوریه '23
+10
در 0 کانالها
Get PRO
ژانویه '23
+14
در 0 کانالها
Get PRO
دسامبر '22
+13
در 0 کانالها
Get PRO
نوامبر '22
+41
در 0 کانالها
Get PRO
اکتبر '22
+81
در 0 کانالها
Get PRO
سپتامبر '22
+5
در 0 کانالها
Get PRO
اوت '22
+5
در 0 کانالها
Get PRO
ژوئیه '22
+8
در 0 کانالها
Get PRO
ژوئن '22
+4
در 0 کانالها
Get PRO
مه '22
+12
در 0 کانالها
Get PRO
آوریل '22
+7
در 0 کانالها
Get PRO
مارس '22
+41
در 0 کانالها
Get PRO
فوریه '22
+6
در 0 کانالها
Get PRO
ژانویه '22
+7
در 0 کانالها
Get PRO
دسامبر '21
+36
در 0 کانالها
Get PRO
نوامبر '21
+3
در 0 کانالها
Get PRO
اکتبر '21
+1
در 0 کانالها
Get PRO
سپتامبر '21
+13
در 0 کانالها
Get PRO
اوت '21
+11
در 0 کانالها
Get PRO
ژوئیه '210
در 0 کانالها
Get PRO
ژوئن '21
+11
در 0 کانالها
Get PRO
مه '21
+14
در 0 کانالها
Get PRO
آوریل '21
+20
در 0 کانالها
Get PRO
مارس '21
+37
در 0 کانالها
Get PRO
فوریه '21
+6
در 0 کانالها
Get PRO
ژانویه '21
+18
در 0 کانالها
Get PRO
دسامبر '20
+342
در 0 کانالها
| تاریخ | رشد مشترکین | اشارات | کانالها | |
| 21 دسامبر | 0 | |||
| 20 دسامبر | 0 | |||
| 19 دسامبر | 0 | |||
| 18 دسامبر | +1 | |||
| 17 دسامبر | 0 | |||
| 16 دسامبر | 0 | |||
| 15 دسامبر | 0 | |||
| 14 دسامبر | 0 | |||
| 13 دسامبر | 0 | |||
| 12 دسامبر | 0 | |||
| 11 دسامبر | +1 | |||
| 10 دسامبر | +1 | |||
| 09 دسامبر | +1 | |||
| 08 دسامبر | +3 | |||
| 07 دسامبر | 0 | |||
| 06 دسامبر | +1 | |||
| 05 دسامبر | 0 | |||
| 04 دسامبر | 0 | |||
| 03 دسامبر | 0 | |||
| 02 دسامبر | +1 | |||
| 01 دسامبر | +1 |
پستهای کانال
Новый черновик JEP: Derived Record Creation (Preview)
Предлагается ввести новую синтаксическую конструкцию для удобного преобразования записей:
e with { ... }.
Например, есть запись:
record Point(int x, int y, int z) { }
Пример преобразования:
Point newLoc = oldLoc with {
x *= 2;
y *= 2;
z *= 2;
};
Это будет логически эквивалентно (но намного короче):
Point newLoc = switch (oldLoc) {
case Point(var x, var y, var z) -> {
x *= 2;
y *= 2;
z *= 2;
yield new Point(x, y, z);
}
};
#record| 2 | Языку Scala сегодня исполнилось 20 лет. Релиз первой публичной версии Scala произошёл 20 января 2004 года. | 918 |
| 3 | Как известно, ваш фреймворк ни о чём, если не поддерживает fluent API. Поэтому, чтобы поспевать за модными трендами, в SLF4J 2.0 полтора года назад его решили добавить.
То есть если раньше писали:
log.info("Hello world");
То сейчас можно писать:
log.atInfo().log("Hello world");
Это более круто и молодёжно.
Или вместо:
log.debug("firstName={}, lastName={}", firstName, lastName);
Можно писать:
log.atDebug().addKeyValue("firstName", firstName).addKeyValue("lastName", lastName).log();
Ну не красота ли?
Ладно, sarcasm mode off. Если серьёзно, то я действительно не вижу такой уж гигантской пользы от fluent API в SLF4J 2.0. В моём коде сейчас нет ни одного лога, где бы я использовал такие цепочки. Я продолжаю писать всё по старинке. Это короче и читабельнее. Но на ум приходит вот такой случай. Допустим, мне очень сильно важна производительность и я не хочу, чтобы мои логи генерировали какого-либо лишнего мусора. В таком случае мне бы пришлось что-то делать с логами с тремя или более параметрами:
log.debug("Full name is {} {} {}", firstName, middleName, lastName);
Если уровень DEBUG отключен, то в этом случае всегда будет создаваться ненужный массив, т.к. у Logger есть только перегрузки с одним и двумя параметрами, а дальше уже только Object....
Можно обернуть строку в if (log.isDebugEnabled()) {...}, но станет некрасиво. Но можно как раз использовать fluent API:
log.atDebug().addArgument(firstName).addArgument(middleName).addArgument(lastName).log("Full name is {} {} {}");
Здесь нет никаких массивов, а atDebug() в рантайме всегда возвращает синглтон, так что ничего лишнего выделиться не должно. В версии SLF4J 2.1, которая скоро выйдет, код будет выглядеть покороче:
log.atDebug().arg(firstName).arg(middleName).arg(lastName).log("Full name is {} {} {}");
А что вы думаете про новый fluent API в SLF4J 2.0? Используете ли? И в каких случаях?
#slf4j | 1 227 |
| 4 | Пока мы тут обсуждаем Java 22, уже первые три JEP'а появились в Java 23:
• Финальные шаблонные строки: String Templates (Final)
• Финальные неявные классы: Implicitly Declared Classes and Instance Main Methods (Final)
• Превью примитивных типов в паттернах: Primitive types in Patterns, instanceof, and switch (Preview)
#java23 | 866 |
| 5 | В Java 22 появится новый класс ListFormat, с помощью которого можно форматировать списки согласно указанной локали.
List<Integer> list = List.of(1, 2, 3, 4);
var formatDefault = ListFormat.getInstance();
var formatUS = ListFormat.getInstance(Locale.US, ListFormat.Type.STANDARD, ListFormat.Style.FULL);
var formatGerman = ListFormat.getInstance(Locale.GERMAN, ListFormat.Type.STANDARD, ListFormat.Style.FULL);
var formatUnit = ListFormat.getInstance(Locale.US, ListFormat.Type.UNIT, ListFormat.Style.SHORT);
var formatNarrow = ListFormat.getInstance(Locale.US, ListFormat.Type.UNIT, ListFormat.Style.NARROW);
var formatCustom = ListFormat.getInstance(new String[] {"{0};{1}", "{0};{1}", "{0};{1}", "", ""});
System.out.println(formatDefault.format(list)); // 1, 2, 3 и 4
System.out.println(formatUS.format(list)); // 1, 2, 3, and 4
System.out.println(formatGerman.format(list)); // 1, 2, 3 und 4
System.out.println(formatUnit.format(list)); // 1, 2, 3, 4
System.out.println(formatNarrow.format(list)); // 1 2 3 4
System.out.println(formatCustom.format(list)); // 1;2;3;4
Также можно и парсить строки обратно в списки:
List<String> list = formatUS.parse("1,2,3");
System.out.println(list); // [1,2,3]
#java22 | 1 060 |
| 6 | Thread.resume() и Thread.suspend() будут окончательно удалены в Java 23. Они стали deprecated ещё аж в Java 1.2. Но удалят их только сейчас.
Thread.stop() пока что остаётся, поскольку есть ещё довольно много кода, который ссылается на этот метод (правда какой толк, если stop() всё равно бросает UnsupportedOperationException с Java 19).
Кстати, это скрин с сайта javaalmanac.io Очень удобный сайт, рекомендую. | 1 087 |
| 7 | Давайте поговорим про валидацию входных аргументов. На первый взгляд тема кажется совсем банальной, но есть в ней несколько нюансов, которым, на мой взгляд, уделяют недостаточно внимания.
Есть, к примеру, следующая запись:
public record Employee(String firstName, String lastName) {}
Чего здесь не хватает? Правильно, проверок на null для firstName и lastName. Ну так давайте добавим:
public record Employee(String firstName, String lastName) {
public Employee {
if (firstName == null) {
throw new NullPointerException("firstName must not be null");
}
if (lastName == null) {
throw new NullPointerException("lastName must not be null");
}
}
}
Как-то слишком длинно. Если у нас в проекте сотни подобных проверок (все ж пишут проверки, так ведь?🙂), то код сильно раздувается. Хочется покомпактнее. Вспоминаем, что в Java 8 появился метод Objects.requireNonNull(). Заменяем:
public Employee {
Objects.requireNonNull(firstName, "firstName must not be null");
Objects.requireNonNull(lastName, "lastName must not be null");
}
Гораздо лучше. Но теперь вспоминаем, что firstName и lastName также не могут быть пустыми. Objects.requireNonNull() тут уже не поможет. Придётся опять писать трёхстрочные if’ы? Не хочется. Можно создать какой-нибудь утилитный метод типа checkCondition(). Но наверняка в какой-нибудь библиотеке такое уже есть? Я в течение своей многолетней практики сталкивался с разными вариантами и в конце концов понял, что всё-таки лучшим образом эту проблему решили в Guava. В классе Preconditions:
public Employee {
...
Preconditions.checkArgument(!firstName.isEmpty(), "firstName must not be empty");
Preconditions.checkArgument(!lastName.isEmpty(), "lastName must not be empty");
}
Есть там и другие проверки: checkNotNull(), checkElementIndex(), checkPositionIndex(), checkState(). При этом checkArgument() из них самый универсальный, и с его помощью можно проверить любое boolean выражение:
Preconditions.checkArgument(firstName != null && !firstName.isEmpty(), "firstName must not be null or empty");
Preconditions.checkArgument(lastName != null && !lastName.isEmpty(), "lastName must not be null or empty");
В итоге мы смогли уложиться в две строчки, что очень хорошо: проверки не должны занимать много места.
В Гуаве при этом решено ещё несколько проблем.
Представим, что нам ещё надо добавить проверку на максимальную длину строки. Мы пишем в обычном if-стиле и случайно допускаем ошибку в шаблоне:
if (firstName.length() > MAX_LENGTH) {
throw new IllegalArgumentException(String.format("firstName is too long, max length is %s, got %s", MAX_LENGTH));
}
Если в рантайме firstName оказался слишком длинным, то выбросится исключение, но совсем не IllegalArgumentException с красивым сообщением, а что-то совсем другое (MissingFormatArgumentException). Обидно. Гуава в этом плане более снисходительна. Вариант с Preconditions будет в любом случае бросать llegalArgumentException:
Preconditions.checkArgument(firstName.length() <= MAX_LENGTH, "firstName is too long, max length is %s, got %s", MAX_LENGTH);
Конечно, тут сообщение будет неполное. Но это лучше, чем совершенное левое исключение, не связанное с исходной ошибкой.
Другая фишка – это стремление Гуавы не генерировать мусора. Все помнят, что в Java есть боксинг, а это значит, что простая сигнатура checkArgument() с Object… создавала бы обёртки над примитивными значениями каждый раз. Мелочь, но всё равно не очень приятно. Но в Гуаве у checkArgument() есть множество перегрузок для большинства простых случаев.
Например, в этом случае мусора не будет вообще, так как есть перегрузка checkArgument(boolean, String, int, int):
Preconditions.checkArgument(firstName.length() <= MAX_LENGTH, "firstName is too long, max length is %s, got %s", MAX_LENGTH, firstName.length());
Таким образом, Preconditions в Гуаве – это:
1. Компактно
2. Безопасно
3. Эффективно
В общем, рекомендую. Валидировать аргументы надо, и надо делать это с хорошими сообщениями.
#guava | 1 798 |
| 8 | Сравнение производительности сборщиков мусора в Java 8, 17 и 21 (throughput, latency, pause times, memory overhead).
TLDR:
• Java 8 значительно хуже почти по всем параметрам, чем 17 и 21. Срочно апгрейдимся, если ещё на 8.
• 21 лучше 17 не настолько сильно, но разница тоже ощутима.
• G1 самый экономный сборщик в плане памяти из трёх.
• ZGC кушает много, но это трейдофф, благодаря которому возможны паузы < 1ms.
• Generational ZGC лучше, чем legacy ZGC. Так что обязательно включаем ключ -XX:+ZGenerational (если вы на 21 и у вас ZGC). В будущем legacy ZGC исчезнет полностью. | 1 241 |
| 9 | Брайн Гетц предложил идею расширить возможности оператора switch ещё больше, добавив в него возможность обрабатывать исключения в ветках case. Напомню, что с Java 21 switch поддерживает паттерны, записи и case null. По его мнению этого недостаточно, т.к. с помощью них можно обработать только успешные результаты, но для ошибок приходится прибегать к классическому оператору try-catch. Было бы классно, если бы исключения можно было обрабатывать в той же манере, что и успешные результаты, т.е. прямо в ветках switch.
Примеры:
String allLines = switch (Files.readAllLines(path)) {
case List<String> lines -> lines.stream().collect(Collectors.joining("\n"));
case throws IOException _ -> "";
}
var opt = switch (Integer.parseInt(s)) {
case int i -> Optional.of(i);
case throws NumberFormatException _ -> Optional.empty();
};
#switch | 1 924 |
| 10 | JetBrains запустил JetBrains AI. Это AI ассистент в IDE, который умеет многое, например, может объяснить код, предложить рефакторинг, предложить мультистроковое автодополнение, сконвертировать код в другой язык, сгенерировать коммит-сообщение, документацию, юнит-тесты и т.д. и т.п. Всё это он может, потому что глубоко анализирует окружающий контекст (текущий файл, проект, зависимости, язык...)
Также есть AI чат с ассистентом.
Ассистент работает через JetBrains AI Service, который в свою очередь использует OpenAI.
Подписка, разумеется, платная: 100$ в год или 10$ в месяц, если помесячно. Есть free trial. При этом сама IDE должна быть с лицензией (IDEA Community не подойдёт).
Чтобы включить ассистента, нужно обновиться до IDEA 2023.3.
#idea | 1 401 |
| 11 | Время старта Spring-приложения на Java 17 и Java 21. То есть не трогая код и просто обновив версию Java, можно получить заметное сокращение времени старта.
Не сидите на старых версиях Java, обновляйтесь. | 1 537 |
| 12 | Вышел Spring Boot 3.2.0.
Подробные Release Notes можно посмотреть здесь.
#spring | 498 |
| 13 | Что там по Java 22? Список JEP'ов на текущий момент такой (и я думаю, окончательный):
JEP 456: Unnamed Variables & Patterns
JEP 459: String Templates (Second Preview)
JEP 447: Statements before super(...) (Preview)
JEP 455: Primitive types in Patterns, instanceof, and switch (Preview)
JEP 463: Implicitly Declared Classes and Instance Main Methods (Second Preview)
JEP 457: Class-File API (Preview)
JEP 461: Stream Gatherers (Preview)
JEP 454: Foreign Function & Memory API
JEP 460: Vector API (Seventh Incubator)
JEP 462: Structured Concurrency (Second Preview)
JEP 423: Region Pinning for G1
JEP draft: Scoped Values (Second Preview)
Список довольно внушительный, но если отбросить превью/инкубаторы, то остаётся только Unnamed Variables & Patterns, Foreign Function & Memory API и Region Pinning for G1. В принципе, безымянные переменные/паттерны – неплохая фича, я бы попробовал.
А что вы думаете? Будете переходить на Java 22 с 21, когда выйдет? 😆 Ну а если серьёзно, то всё это станет стабильным в следующем LTS (Java 25), и это будет действительно мощный релиз (может, там даже и Valhalla будет).
#java22 | 885 |
| 14 | Вышел Spring 6.1 GA 🥳
Вместе с ним выходит Spring Boot 3.2, но это произойдёт 23 ноября, так что надо чуть-чуть подождать.
В релизе Spring 6.1 тонна всего нового, но главная фишка – это, конечно же, поддержка виртуальных потоков. Включаются они флагом spring.threads.virtual.enabled=true (требуется JDK 21+). С виртуальными потоками можно спокойно вызывать блокирующее API и ни о чём не беспокоиться.
Ещё из интересного:
Новый интерфейс RestClient. Он синхронный, как и старый RestTemplate, но имеет современное удобное fluent API, похожее на WebClient, появившийся в Spring 5. Он не использует WebFlux, а значит не требует зависимости spring-webflux. Т.к. теперь есть виртуальные потоки, то синхронность уже не является проблемой и не вредит масштабируемости. RestClient, как и WebClient, разумеется, поддерживает декларативные HTTP-клиенты, созданные из интерфейсов с аннотациями @HttpExchange.
Новый интерфейс JdbcClient. Это современная альтернатива JdbcTemplate с fluent API:
Optional<Integer> value = client.sql("SELECT AGE FROM CUSTOMER WHERE ID = :id")
.param("id", 3)
.query(Integer.class)
.optional();
Ещё появилась поддержка CRaC, поддержка @HttpExchange аннотаций в MVC-контроллерах и многое другое. Подробный список можно посмотреть тут.
#spring | 1 423 |
| 15 | Предложение в итоге вылилось в JEP 461: Stream Gatherers (Preview) | 458 |
| 16 | 🤩 Встречайте — звёздная конференция Podlodka Java Crew!
Уже 23 октября стартует третий сезон — «Работа с базой данных». Тема настолько обширная, что мы собрали 15 сессий вместо привычных 10. Это ориентированные на практику доклады, воркшопы и круглые столы.
Вас ждёт глубокое погружение в непростую тему взаимоотношений с базами данных:
📌 Научимся использовать sharded redis в нагруженных сервисах рекомендаций.
📌 Рассмотрим эволюцию алгоритмов распределённых транзакций, ограничения и способы их преодолеть.
📌 Проведём публичное собеседование по траблшутингу.
📌 Заглянем в историю версионирования баз данных и практику их использования.
Больше подробностей и билеты — на сайте: https://podlodka.io/javacrew | 490 |
| 17 | И что, хотите сказать, что после этого Java не лучший язык? 🧐 | 587 |
| 18 | Дно пробито | 1 457 |
| 19 | Вышла сразу пачка новых JEP'ов.
JEP 456: Unnamed Variables and Patterns
Безымянные переменные и паттерны станут стабильными в Java 22 после всего одного раунда превью.
JEP: String Templates (Final)
Шаблонные строки, похоже, тоже станут стабильными в Java 22.
JEP: Implicitly Declared Classes and Instance Main Method (2nd Preview)
Безымянные классы хотят переименовать в implicitly declared классы.
JEP 455: Primitive types in Patterns, instanceof, and switch (Preview)
Можно будет писать if (obj instanceof int). Вангую, что тоже попадёт в Java 22.
JEP 457: Class-File API (Preview)
API для чтения, записи и трансформации Java class-файлов. Кстати, оно уже есть в Java 21, но в internal пакете jdk.internal.classfile. В Java 22 станет preview.
#java22 | 1 046 |
| 20 | https://t.me/miniJUG?boost | 1 034 |
