microJUG – Telegram
microJUG
983 subscribers
155 photos
1 video
2 files
237 links
Мысли о Java.
Основной канал: @miniJUG
Буст: https://news.1rj.ru/str/microJUG?boost
Чат: https://news.1rj.ru/str/micro_JUG
Таблица JEP'ов: https://minijug.org/jeps.html
Download Telegram
В 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
17🔥8
Пока мы тут обсуждаем 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
22👍1😨1
Как известно, ваш фреймворк ни о чём, если не поддерживает 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
🤮28👍6😁5🤔11
Языку Scala сегодня исполнилось 20 лет. Релиз первой публичной версии Scala произошёл 20 января 2004 года.
🍾12🎉52
Новый черновик 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
🤯2813👍4🔥3🤡2🤨2
Новые JEP'ы.

JEP 467: Markdown Documentation Comments
Предлагается ввести новый тип JavaDoc'а на основе Markdown в качестве альтернативы старому на основе HTML. Такой JavaDoc использует /// вместо /** ... */:

Старый:
/**
* Returns a hash code value for the object. This method is
* supported for the benefit of hash tables such as those provided by
* {@link java.util.HashMap}.
*/


Новый:
/// Returns a hash code value for the object. This method is
/// supported for the benefit of hash tables such as those provided by
/// [java.util.HashMap].


JEP 468: Derived Record Creation (Preview)
Предлагается добавить в язык with'еры для записей:

record Point(int x, int y, int z) { }

Point nextLoc = oldLoc with {
x *= 2;
y *= 2;
z *= 2;
};


Это особенно удобно, когда нужно изменить только один компонент записи из многих:
record User(int id, String firstName, String lastName, String email) {}

var newUser = oldUser with { id = 42 };
🔥1412👍9
Озвучено новое предложение по String Templates. Предлагается избавиться от интерфейса Processor и оставить только StringTemplate. То есть больше не будет никаких STR."...", RAW."..." и FMT."...", и можно будет просто писать:

System.out.println("Hello \{name}");
String s = String.format("Hello %12s\{name}");


Чтобы это стало возможным, библиотекам нужно будет добавить явную поддержку аргументов StringTemplate:

public class PrintStream {
...
public void println(String);
public void println(StringTemplate);
}

public class String {
...
public String format(String, Object...);
public String format(StringTemplate);
}


Однако пока остаётся открытым вопрос, что делать, если нужно просто интерполировать шаблонную строку в String. Похоже, что будет какой-то новый метод вроде join():

String s = "Hello \{name}".join();
👍54😁2
Пользователям macOS Sonoma на Apple Silicon не рекомендуется обновляться до версии 14.4, так как после этого Java-процессы могут неожиданно терминироваться. Проблема затрагивает все версии Java с 8 по 22. Обходного пути нет. Также после обновления у вас не будет простого способа откатиться на предыдущую версию macOS.
#macos
🤣138💩4👏3🤬2🔥1
Завтра что-то выйдет
😱17🎉127👻6
Ежегодный опрос. Какую версию(-и) Java или язык JVM вы используете на работе?
Anonymous Poll
16%
Java 8 или более старую
24%
Java 11
0%
Java 12-16
62%
Java 17
2%
Java 18-20
26%
Java 21
1%
Java 22
18%
Kotlin
2%
Scala
5%
Groovy
4🤯1
Спрингу исполнилось 20 лет. 24 марта 2004 года вышел Spring Framework 1.0 Final.
🎉39🍾5🔥2🤯1
Сегодня с ребятами из каналов @javaswag и @staff_engineers будем обсуждать новые фичи в Java 22. Стрим начнётся в 20:30 по Москве. Приходите, будет интересно.

https://www.youtube.com/watch?v=8E_g-VHJCtw
5👍31🥱1🥴1
Баг с крэшем JVM исправили в macOS 14.4.1. Так что теперь можно обновляться.
#macos
🔥1411🌚3👍1
Новый черновик JEP: Module Import Declarations (Preview).

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

import module java.base;


Это то же самое, что вручную написать import для всех пакетов, экспортированных в модуле java.base:

import java.io.*;
import java.util.*;
import java.util.function.*;
... // ещё 51 импорт
💩9🤯8🔥5🤔44
Брайан Гетц написал огромное письмо в рассылку, где впервые очень подробно и с конкретными примерами синтаксиса написал, как могут выглядеть member-паттерны (паттерны-члены). Напомню, что в Java сейчас есть только паттерны у записей. Member-паттерны позволят объявлять паттерны в любых классах. Рассмотрим несколько примеров:

Паттерн-деконструктор:
class Point {
int x, y;

Point(int x, int y) {
this.x = x;
this.y = y;
}

pattern Point(int x, int y) {
matches Point(that.x, that.y);
}
}


Статические паттерны:
class Optional<T> {
static<T> Optional<T> of(T t) { ... }
static<T> Optional<T> empty() { ... }

static<T> case pattern(Optional<T> that) of(T t) {
if (that.isPresent())
matches of(that.get());
}

static<T> case pattern(Optional<T> that) empty() {
if (that.isEmpty())
matches empty();
}
}


(В примере выше case нужен для проверки exhaustiveness компилятором)

Далее такие статические паттерны можно уже применять в switch или instanceof:
case Optional.of(var e): ...
case Optional.empty(): ...


Инстанс-паттерны:
public class Class<T> {
...

pattern arrayClass(Class<?> componentType) {
if (that.isArray())
matches arrayClass(that.getComponentType());
}
}


package java.util.regex;

public class Pattern
...
pattern(String that) regexMatch(String... groups) {
Matcher m = matcher(that);
if (m.matches())
matches Pattern.regexMatch(IntStream.range(1, m.groupCount())
.map(Matcher::group)
.toArray(String[]::new));
}
}


Использование:
int[] array = {1,2,3,4,5};
Class<?> clazz = array.class;
if (clazz instanceof arrayClass(componentType)) {
...
}

static Pattern As = Pattern.compile("(a*)");
static Pattern Bs = Pattern.compile("(b*)");
...

String str = "aaaa";
switch (str) {
case As.regexMatch(var as): ...
case Bs.regexMatch(var bs): ...
...
}


Как-то так.

#patternmatching
🤯27👍7💩5👀4🤮22🤔1
🔥14👌9👍3👏1
😥 String Templates всё. В Java 23 их не будет, даже с --enable-preview.
😢17👀10👍8😁5🤯5🍾4🔥1
⚰️ JetBrains закрывает Space. Причина – низкая востребованность продукта. Новые подписки больше не продаются, а для существующих будет работать поддержка и будут выходить критические обновления до 31 мая 2025 года.
Вместо Space JetBrains будет развивать новый продукт SpaceCode, который будет платформой для Git-хостинга и код-ревью (аналог GitHub/GitLab).
#jetbrains #spacecode
Please open Telegram to view this post
VIEW IN TELEGRAM
7👍2👨‍💻1
Сегодня начинается Rampdown Phase One для JDK 23. Окончательный список фич:

455: Primitive Types in Patterns, instanceof, and switch (Preview)
466: Class-File API (Second Preview)
467: Markdown Documentation Comments
469: Vector API (Eighth Incubator)
473: Stream Gatherers (Second Preview)
471: Deprecate the Memory-Access Methods in sun.misc.Unsafe for Removal
474: ZGC: Generational Mode by Default
476: Module Import Declarations (Preview)
477: Implicitly Declared Classes and Instance Main Methods (Third Preview)
480: Structured Concurrency (Third Preview)
481: Scoped Values (Third Preview)
482: Flexible Constructor Bodies (Second Preview)

Как обычно, сплошные превью и инкубаторы. Из стабильного только Markdown Documentation Comments, но я не думаю, что прям все ринутся писать джавадоки в новом формате. Хотя, может, кто-то и будет.

#java23
14🫡7🤯1🥱1
Maven Daemon вышел из беты. Зарелизился mvnd 1.0.0 (и уже 1.0.1). 1.0.0 соответствует Apache Maven 3.9.8.

А вы юзаете mvnd? Я уже юзаю давно. Работает отлично. Работает гораздо быстрее, чем простой Maven.

#maven #mvnd
🎄8👍6👀4👎2🎉2🙈2🔥1
Сбер выпустил открытую среду разработки Giga IDE на базе IntelliJ IDEA/Pycharm со встроенным ИИ-ассистентом GigaCode. Среда доступна в двух вариантах: Giga IDE Desktop и Giga IDE Cloud.

Вскоре после выхода разработчик из JetBrains Юрий Артамонов обнаружил, что в кодовой базе GigaIDE содержится проприетарный код из IntelliJIDEA Ultimate.

СпёрIDE.

Update: Юрий Артамонов разобрался, что Giga IDE всё-таки не нарушает лицензию, так как использует только свободное API.
Но GigaIDE всё-таки будет у нас на карандаше 😉.

#gigaide #gigacode
💩28🤣19👍7🤡3😭3😁2