#java #reflection #java-9
#java #отражение #java-9
Вопрос:
Есть ли какой-либо способ преобразовать из a VarHandle
в a java.lang.reflect.Field
? С помощью (getter / setter) MethodHandle
можно использовать MethodHandles.reflectAs(Field.class, handle)
для перехода от MethodHandle
к Field
или lookup.unreflect{Getter|Setter}(field)
для перехода от Field
к MethodHandle
. Аналогично, можно использовать lookup.unreflectVarHandle(field)
для перехода от Field
к VarHandle
, но, похоже, нет никакого эквивалентного способа перехода от VarHandle
к Field
.
Ответ №1:
Похоже, такая функция действительно отсутствует.
Но, начиная с JDK 12, вы можете эмулировать его через constant API:
Optional<Field> o = varHandle.describeConstable().map(d -> {
String mName = d.bootstrapMethod().methodName();
if(mName.equals("staticFieldVarHandle") || mName.equals("fieldVarHandle")) try {
return ((Class<?>)((ClassDesc)d.bootstrapArgsList().get(0))
.resolveConstantDesc(MethodHandles.lookup()))
.getDeclaredField(d.constantName());
} catch (ReflectiveOperationException ex) {}
return null;
});
Это обеспечивает Field
, когда VarHandle
описывается доступное поле.
Комментарии:
1. Хороший трюк, но немного не хватает, поскольку поле должно быть доступным, тогда
MethodHandles.reflectAs
как работает, даже если поле недоступно. Интересно, что способ, которым Java 12 реализует этотdescribeConstable
метод, заключается не в добавленииMethodName
вVarHandle
anywhere , а в добавленииVarHandles.getFieldFromReceiverAndOffset
иVarHandles.getStaticFieldFromBaseAndOffset
, которые возвращаютField
и могут быть тривиально использованы для реализации чего-то подобногоVarHandle.reflect
.2. Ну, обычно, в первую очередь нелегко создать a
VarHandle
для недоступного поля. Не то, чтобы ограничение доступности применялось только к классу owner, затем поле просматривается через обычныйgetDeclaredField
, который может видеть недоступные поля. В принципе, вы могли бы даже извлечь имя класса и выполнить поиск самостоятельно. Но да, это все равно не будет таким же, как areflectAs
, который работает независимо от контекста вызывающего.3. Я думаю о случае, когда VarHandle создается из вызывающего объекта, который может видеть поле, а затем передается служебному классу, который не может (например, что-то вроде AtomicReferenceFieldUpdater). Если служебному классу требуется дескриптор отраженного поля (для утверждений типа или тому подобного), простого способа его получить нет. Альтернативой является вместо этого передача MethodHandle . Поиск и имя поля, и пусть служебный класс выполняет поиск поля (отражается на дескрипторе getter) и самого varhandle .
4. Я думаю, мы согласны с тем, что это недостающая функция…