Найти в Дзене

Переменные с областью действия

Ещё одно интересное нововведение, которое ждёт нас в грядущем релизе JDK 25 — переменные с областью действия. Наверняка многие сталкивались с ситуацией, когда нужно передать какую-то информацию между двумя компонентами, но при этом по каким-то причинам не хочется добавлять новые аргументы в методы или свойства в классы. Зачастую такая задача решалась при помощи ThreadLocal - локальных переменных потока. В одном месте данные добавлялись в локальные переменные потока, а в другом - извлекались. Но у локальных переменных потоков есть свои недостатки и достаточно существенные. И именно недостатки ThreadLocal побудили разработчиков JDK придумать новый инструмент, позволяющий объявлять переменные в некоторой области действия. Переменные с областью действия находились в разработке с JDK 20 и к релизу JDK 25 стали стабильными. Переменные с областью действия описываются типизированным классом ScopedValue<T>, где тип соответствует типу данных переменной. Данный класс предоставляет следующие метод

Ещё одно интересное нововведение, которое ждёт нас в грядущем релизе JDK 25 — переменные с областью действия.

Наверняка многие сталкивались с ситуацией, когда нужно передать какую-то информацию между двумя компонентами, но при этом по каким-то причинам не хочется добавлять новые аргументы в методы или свойства в классы. Зачастую такая задача решалась при помощи ThreadLocal - локальных переменных потока. В одном месте данные добавлялись в локальные переменные потока, а в другом - извлекались. Но у локальных переменных потоков есть свои недостатки и достаточно существенные. И именно недостатки ThreadLocal побудили разработчиков JDK придумать новый инструмент, позволяющий объявлять переменные в некоторой области действия.

Переменные с областью действия находились в разработке с JDK 20 и к релизу JDK 25 стали стабильными. Переменные с областью действия описываются типизированным классом ScopedValue<T>, где тип соответствует типу данных переменной. Данный класс предоставляет следующие методы:

  • newInstance() — метод класса для создания переменной с областью действия
  • where() — метод класса для присвоения значения и получения его носителя
  • get() — для получения значения переменной для текущей области действия
  • isBound() — для проверки наличия присвоенного значения
  • orElse() — для получения текущего значения или альтернативного
  • orElseThorw() — для получения текущего значения или выбрасывания исключения

Носитель значения описывается классом ScopedValue.Carrier и предоставляет следующие методы:

  • get() — для получения значения для текущей области действия
  • where() — для присвоения нового значения и получения дочернего носителя

Пример использования переменных с областью действия:

// Создание новой строковой переменной с областью действия
ScopedValue<
String> scopedValue = ScopedValue.newInstance();

// Присваивание значения и получение носителя
ScopedValue.Carrier carrier = ScopedValue.where(scopedValue, "foo");

// Выполнение кода с передачей переменной
carrier.run(() -> {
// Здесь значение переменной - foo
// Выведет foo
IO.println(scopedValue.get());

// Присваивание значения и получение нового носителя
ScopedValue.where(scopedValue, "bar").run(() -> {
// А здесь значение переменной - bar
// Выведет bar
IO.println(scopedValue.get());
});

// В этой области действия значение осталось прежним - foo
// Выведет foo
IO.println(scopedValue.get());
});

// К текущему значению можно получить доступ через носитель
// Выведет foo
IO.println(carrier.get());

// Так делать нельзя, так как для текущей области действия
// значение не назначено, и будет выброшено
// исключение NoSuchElementException
scopedValue.get();

Наука
7 млн интересуются