Spec-Zone.ru › OpenJDK 24

Класс ClassValue<T>

java.lang.Object
java.lang.ClassValue<T>
Параметры типа:
T - тип производного значения
public abstract class ClassValue<T> extends Object
Лениво связывает вычисленное значение с (потенциально) каждым типом. Например, если динамическому языку нужно создать таблицу диспетчеризации сообщений для каждого класса, встреченного в месте отправки сообщения, он может использовать ClassValue для кеширования информации, необходимой для быстрого отправки сообщения для каждого встреченного класса.
С:
1.7

Краткое описание конструкторов

ClassValue()
Модификатор Конструктор Описание
protected
Единственный конструктор.

Краткое описание методов

Модификатор и тип Метод Описание
protected abstract T computeValue(Class<?> type)
Вычисляет производное значение данного класса для этого ClassValue.
T get(Class<?> type)
Возвращает значение для данного класса.
void remove(Class<?> type)
Удаляет связанное значение для данного класса.

Методы, объявленные в классе java.lang.Object

clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Подробное описание конструкторов

ClassValue

protected ClassValue()
Единственный конструктор. (Для вызова конструкторами подклассов, как правило, неявным).

Подробное описание методов

computeValue

protected abstract T computeValue(Class<?> type)
Вычисляет производное значение данного класса для этого ClassValue.

Этот метод будет вызван в первой потоке, которая обращается к значению с методом get.

Обычно этот метод вызывается не более одного раза на класс, но он может быть вызван снова, если был вызов remove.

Если этот метод вызывает исключение, соответствующий вызов get завершится с этим исключением аномально, и значение класса не будет записано.

Параметры:
type - тип, значение класса которого нужно вычислить
Возвращает:
нововычисленное значение, связанное с этим ClassValue, для данного класса или интерфейса
См. также:
  • get(java.lang.Class<?>)
  • remove(java.lang.Class<?>)

get

public T get(Class<?> type)
Возвращает значение для данного класса. Если значение еще не вычислено, оно получено путем вызова метода computeValue.

Фактическая установка значения на классе выполняется атомарно. В этот момент, если несколько конкурирующих потоков вычислили значения, выбирается одно и возвращается всем конкурирующим потокам.

Параметр type, как правило, является классом, но он может быть любого типа, такого как интерфейс, примитивный тип (например, int.class) или void.class.

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

Параметры:
type - тип, значение класса которого нужно вычислить или получить
Возвращает:
текущее значение, связанное с этим ClassValue, для данного класса или интерфейса
Исключения:
NullPointerException - если аргумент null
См. также:
  • remove(java.lang.Class<?>)
  • computeValue(java.lang.Class<?>)

remove

public void remove(Class<?> type)
Удаляет связанное значение для данного класса. Если это значение впоследствии считывается для того же класса, его значение будет повторно инициализировано путем вызова его метода computeValue. Это может привести к дополнительному вызову метода computeValue для данного класса.

Для объяснения взаимодействия между вызовами get и remove, необходимо смоделировать переходы состояний значения класса, учитывая чередование между состояниями неинициализированного и инициализированного. Для этого пронумеруем эти состояния последовательно и отметим, что состояния неинициализированного (или удалённого) состояния имеют чётные номера, в то время как состояния инициализированного (или повторно инициализированного) состояния имеют нечётные номера.

Когда поток T удаляет значение класса в состоянии 2N, ничего не происходит, так как значение класса уже неинициализировано. В противном случае состояние атомарно переходит в 2N+1.

Когда поток T запрашивает значение класса в состоянии 2N, поток сначала пытается инициализировать значение класса в состояние 2N+1, вызвав computeValue и установив полученное значение.

Когда T пытается установить нововычисленное значение, если состояние всё ещё находится в 2N, значение класса будет инициализировано вычисленным значением, переведя его в состояние 2N+1.

В противном случае, независимо от того, чётное или нечётное новое состояние, T отбросит нововычисленное значение и повторит операцию get.

Отбрасывание и повторная попытка являются важным дополнением, так как в противном случае T потенциально мог установить катастрофически устаревшее значение. Например:

  • T вызывает CV.get(C) и видит состояние 2N
  • T быстро вычисляет зависимое от времени значение V0 и готовится установить его
  • T испытывает неудачную страничную или планировочную ошибку и переходит в спящее состояние на долгое время
  • ...между тем, T2 также вызывает CV.get(C) и видит состояние 2N
  • T2 быстро вычисляет аналогичное зависимое от времени значение V1 и устанавливает его на CV.get(C)
  • T2 (или третий поток) затем вызывает CV.remove(C), отменяя работу T2
  • предыдущие действия T2 повторяются несколько раз
  • также, соответствующие вычисленные значения изменяются со временем: V1, V2, ...
  • ...между тем, T просыпается и пытается установить V0; это должно завершиться неудачей
Мы можем предположить в описанном выше сценарии, что CV.computeValue использует блокировки для правильного наблюдения за зависимыми от времени состояниями при вычислении V1 и т. д. Это не устраняет угрозу устаревшего значения, так как существует временной интервал между возвращением computeValue в T и установкой нового значения. Пользовательская синхронизация в это время невозможна.
Параметры:
type - тип, значение класса которого необходимо удалить
Исключения:
NullPointerException - если аргумент null

© 1993, 2025, Oracle and/or its affiliates. All rights reserved.
Documentation extracted from Debian's OpenJDK Development Kit package.
Licensed under the GNU General Public License, version 2, with the Classpath Exception.
Various third party code in OpenJDK is licensed under different licenses (see Debian package).
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
https://download.java.net/java/early_access/jdk24/docs/api/java.base/java/lang/ClassValue.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API