2021-11-09 16:16:35 +01:00
|
|
|
package com.google.gson.internal.reflect;
|
|
|
|
|
|
|
|
import com.google.gson.JsonIOException;
|
2022-04-17 18:05:18 +02:00
|
|
|
import com.google.gson.internal.GsonBuildConfig;
|
2022-10-12 23:24:36 +02:00
|
|
|
import java.lang.reflect.AccessibleObject;
|
|
|
|
import java.lang.reflect.Constructor;
|
|
|
|
import java.lang.reflect.Field;
|
|
|
|
import java.lang.reflect.Method;
|
2021-11-09 16:16:35 +01:00
|
|
|
|
|
|
|
public class ReflectionHelper {
|
Support Java Records when present in JVM. (#2201)
* Support Java Records when present in JVM.
Fixes google/gson#1794
Added support in the ReflectionHelper to detect if a class is a record
on the JVM (via reflection), and if so, we will create a special
RecordAdapter to deserialize records, using the canoncial constructor.
The ReflectionTypeAdapterFactory had to be refactored a bit to support
this. The Adapter class inside the factory is now abstract, with
concrete implementations for normal field reflection and for Records.
The common code is in the Adapter, with each implementation
deserializing values into an intermediary object.
For the FieldReflectionAdapter, the intermediary is actually the final
result, and field access is used to write to fields as before. For the
RecordAdapter the intermediary is the Object[] to pass to the Record
constructor.
* Fixed comments from @Marcono1234
Also updated so that we now use the record accessor method to read out
values from a record, so that direct field access is not necessary.
Also added some tests, that should only execute on Java versions with
record support, and be ignored for other JVMs
* Fixed additional comments from @Marcono1234
* Made Adapter in ReflectiveTypeAdapterFactory public
Fix comment from @eamonnmcmanus
2022-10-11 18:13:49 +02:00
|
|
|
|
|
|
|
private static final RecordHelper RECORD_HELPER;
|
|
|
|
|
|
|
|
static {
|
|
|
|
RecordHelper instance;
|
|
|
|
try {
|
|
|
|
// Try to construct the RecordSupportedHelper, if this fails, records are not supported on this JVM.
|
|
|
|
instance = new RecordSupportedHelper();
|
|
|
|
} catch (NoSuchMethodException e) {
|
|
|
|
instance = new RecordNotSupportedHelper();
|
|
|
|
}
|
|
|
|
RECORD_HELPER = instance;
|
|
|
|
}
|
|
|
|
|
|
|
|
private ReflectionHelper() {}
|
2021-11-09 16:16:35 +01:00
|
|
|
|
Support Java Records when present in JVM. (#2201)
* Support Java Records when present in JVM.
Fixes google/gson#1794
Added support in the ReflectionHelper to detect if a class is a record
on the JVM (via reflection), and if so, we will create a special
RecordAdapter to deserialize records, using the canoncial constructor.
The ReflectionTypeAdapterFactory had to be refactored a bit to support
this. The Adapter class inside the factory is now abstract, with
concrete implementations for normal field reflection and for Records.
The common code is in the Adapter, with each implementation
deserializing values into an intermediary object.
For the FieldReflectionAdapter, the intermediary is actually the final
result, and field access is used to write to fields as before. For the
RecordAdapter the intermediary is the Object[] to pass to the Record
constructor.
* Fixed comments from @Marcono1234
Also updated so that we now use the record accessor method to read out
values from a record, so that direct field access is not necessary.
Also added some tests, that should only execute on Java versions with
record support, and be ignored for other JVMs
* Fixed additional comments from @Marcono1234
* Made Adapter in ReflectiveTypeAdapterFactory public
Fix comment from @eamonnmcmanus
2022-10-11 18:13:49 +02:00
|
|
|
/**
|
|
|
|
* Internal implementation of making an {@link AccessibleObject} accessible.
|
|
|
|
*
|
|
|
|
* @param object the object that {@link AccessibleObject#setAccessible(boolean)} should be called on.
|
|
|
|
* @throws JsonIOException if making the object accessible fails
|
|
|
|
*/
|
2022-10-22 18:01:56 +02:00
|
|
|
public static void makeAccessible(AccessibleObject object) throws JsonIOException {
|
2021-11-09 16:16:35 +01:00
|
|
|
try {
|
Support Java Records when present in JVM. (#2201)
* Support Java Records when present in JVM.
Fixes google/gson#1794
Added support in the ReflectionHelper to detect if a class is a record
on the JVM (via reflection), and if so, we will create a special
RecordAdapter to deserialize records, using the canoncial constructor.
The ReflectionTypeAdapterFactory had to be refactored a bit to support
this. The Adapter class inside the factory is now abstract, with
concrete implementations for normal field reflection and for Records.
The common code is in the Adapter, with each implementation
deserializing values into an intermediary object.
For the FieldReflectionAdapter, the intermediary is actually the final
result, and field access is used to write to fields as before. For the
RecordAdapter the intermediary is the Object[] to pass to the Record
constructor.
* Fixed comments from @Marcono1234
Also updated so that we now use the record accessor method to read out
values from a record, so that direct field access is not necessary.
Also added some tests, that should only execute on Java versions with
record support, and be ignored for other JVMs
* Fixed additional comments from @Marcono1234
* Made Adapter in ReflectiveTypeAdapterFactory public
Fix comment from @eamonnmcmanus
2022-10-11 18:13:49 +02:00
|
|
|
object.setAccessible(true);
|
2021-11-09 16:16:35 +01:00
|
|
|
} catch (Exception exception) {
|
2022-10-22 18:01:56 +02:00
|
|
|
String description = getAccessibleObjectDescription(object, false);
|
|
|
|
throw new JsonIOException("Failed making " + description + " accessible; either increase its visibility"
|
|
|
|
+ " or write a custom TypeAdapter for its declaring type.", exception);
|
2021-11-09 16:16:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-22 18:01:56 +02:00
|
|
|
/**
|
|
|
|
* Returns a short string describing the {@link AccessibleObject} in a human-readable way.
|
|
|
|
* The result is normally shorter than {@link AccessibleObject#toString()} because it omits
|
|
|
|
* modifiers (e.g. {@code final}) and uses simple names for constructor and method parameter
|
|
|
|
* types.
|
|
|
|
*
|
|
|
|
* @param object object to describe
|
|
|
|
* @param uppercaseFirstLetter whether the first letter of the description should be uppercased
|
|
|
|
*/
|
|
|
|
public static String getAccessibleObjectDescription(AccessibleObject object, boolean uppercaseFirstLetter) {
|
|
|
|
String description;
|
|
|
|
|
|
|
|
if (object instanceof Field) {
|
2022-12-05 02:27:43 +01:00
|
|
|
description = "field '" + fieldToString((Field) object) + "'";
|
2022-10-22 18:01:56 +02:00
|
|
|
} else if (object instanceof Method) {
|
|
|
|
Method method = (Method) object;
|
|
|
|
|
|
|
|
StringBuilder methodSignatureBuilder = new StringBuilder(method.getName());
|
|
|
|
appendExecutableParameters(method, methodSignatureBuilder);
|
|
|
|
String methodSignature = methodSignatureBuilder.toString();
|
|
|
|
|
|
|
|
description = "method '" + method.getDeclaringClass().getName() + "#" + methodSignature + "'";
|
|
|
|
} else if (object instanceof Constructor) {
|
|
|
|
description = "constructor '" + constructorToString((Constructor<?>) object) + "'";
|
|
|
|
} else {
|
|
|
|
description = "<unknown AccessibleObject> " + object.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (uppercaseFirstLetter && Character.isLowerCase(description.charAt(0))) {
|
|
|
|
description = Character.toUpperCase(description.charAt(0)) + description.substring(1);
|
|
|
|
}
|
|
|
|
return description;
|
|
|
|
}
|
|
|
|
|
2022-12-05 02:27:43 +01:00
|
|
|
/**
|
|
|
|
* Creates a string representation for a field, omitting modifiers and
|
|
|
|
* the field type.
|
|
|
|
*/
|
|
|
|
public static String fieldToString(Field field) {
|
|
|
|
return field.getDeclaringClass().getName() + "#" + field.getName();
|
|
|
|
}
|
|
|
|
|
2021-11-09 16:16:35 +01:00
|
|
|
/**
|
|
|
|
* Creates a string representation for a constructor.
|
2022-10-22 18:01:56 +02:00
|
|
|
* E.g.: {@code java.lang.String(char[], int, int)}
|
2021-11-09 16:16:35 +01:00
|
|
|
*/
|
2022-10-22 18:01:56 +02:00
|
|
|
public static String constructorToString(Constructor<?> constructor) {
|
|
|
|
StringBuilder stringBuilder = new StringBuilder(constructor.getDeclaringClass().getName());
|
|
|
|
appendExecutableParameters(constructor, stringBuilder);
|
|
|
|
|
|
|
|
return stringBuilder.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Note: Ideally parameter type would be java.lang.reflect.Executable, but that was added in Java 8
|
|
|
|
private static void appendExecutableParameters(AccessibleObject executable, StringBuilder stringBuilder) {
|
|
|
|
stringBuilder.append('(');
|
|
|
|
|
|
|
|
Class<?>[] parameters = (executable instanceof Method)
|
|
|
|
? ((Method) executable).getParameterTypes()
|
|
|
|
: ((Constructor<?>) executable).getParameterTypes();
|
2021-11-09 16:16:35 +01:00
|
|
|
for (int i = 0; i < parameters.length; i++) {
|
|
|
|
if (i > 0) {
|
|
|
|
stringBuilder.append(", ");
|
|
|
|
}
|
|
|
|
stringBuilder.append(parameters[i].getSimpleName());
|
|
|
|
}
|
|
|
|
|
2022-10-22 18:01:56 +02:00
|
|
|
stringBuilder.append(')');
|
2021-11-09 16:16:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Tries making the constructor accessible, returning an exception message
|
|
|
|
* if this fails.
|
|
|
|
*
|
|
|
|
* @param constructor constructor to make accessible
|
|
|
|
* @return exception message; {@code null} if successful, non-{@code null} if
|
|
|
|
* unsuccessful
|
|
|
|
*/
|
|
|
|
public static String tryMakeAccessible(Constructor<?> constructor) {
|
|
|
|
try {
|
|
|
|
constructor.setAccessible(true);
|
|
|
|
return null;
|
|
|
|
} catch (Exception exception) {
|
2022-10-22 18:01:56 +02:00
|
|
|
return "Failed making constructor '" + constructorToString(constructor) + "' accessible;"
|
|
|
|
+ " either increase its visibility or write a custom InstanceCreator or TypeAdapter for"
|
2021-11-09 16:16:35 +01:00
|
|
|
// Include the message since it might contain more detailed information
|
2022-10-22 18:01:56 +02:00
|
|
|
+ " its declaring type: " + exception.getMessage();
|
2021-11-09 16:16:35 +01:00
|
|
|
}
|
|
|
|
}
|
2022-04-17 18:05:18 +02:00
|
|
|
|
Support Java Records when present in JVM. (#2201)
* Support Java Records when present in JVM.
Fixes google/gson#1794
Added support in the ReflectionHelper to detect if a class is a record
on the JVM (via reflection), and if so, we will create a special
RecordAdapter to deserialize records, using the canoncial constructor.
The ReflectionTypeAdapterFactory had to be refactored a bit to support
this. The Adapter class inside the factory is now abstract, with
concrete implementations for normal field reflection and for Records.
The common code is in the Adapter, with each implementation
deserializing values into an intermediary object.
For the FieldReflectionAdapter, the intermediary is actually the final
result, and field access is used to write to fields as before. For the
RecordAdapter the intermediary is the Object[] to pass to the Record
constructor.
* Fixed comments from @Marcono1234
Also updated so that we now use the record accessor method to read out
values from a record, so that direct field access is not necessary.
Also added some tests, that should only execute on Java versions with
record support, and be ignored for other JVMs
* Fixed additional comments from @Marcono1234
* Made Adapter in ReflectiveTypeAdapterFactory public
Fix comment from @eamonnmcmanus
2022-10-11 18:13:49 +02:00
|
|
|
/** If records are supported on the JVM, this is equivalent to a call to Class.isRecord() */
|
|
|
|
public static boolean isRecord(Class<?> raw) {
|
|
|
|
return RECORD_HELPER.isRecord(raw);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static String[] getRecordComponentNames(Class<?> raw) {
|
|
|
|
return RECORD_HELPER.getRecordComponentNames(raw);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Looks up the record accessor method that corresponds to the given record field */
|
|
|
|
public static Method getAccessor(Class<?> raw, Field field) {
|
|
|
|
return RECORD_HELPER.getAccessor(raw, field);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static <T> Constructor<T> getCanonicalRecordConstructor(Class<T> raw) {
|
|
|
|
return RECORD_HELPER.getCanonicalRecordConstructor(raw);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static RuntimeException createExceptionForUnexpectedIllegalAccess(
|
|
|
|
IllegalAccessException exception) {
|
2022-10-22 18:01:56 +02:00
|
|
|
throw new RuntimeException("Unexpected IllegalAccessException occurred (Gson " + GsonBuildConfig.VERSION + ")."
|
|
|
|
+ " Certain ReflectionAccessFilter features require Java >= 9 to work correctly. If you are not using"
|
|
|
|
+ " ReflectionAccessFilter, report this to the Gson maintainers.",
|
2022-04-17 18:05:18 +02:00
|
|
|
exception);
|
|
|
|
}
|
Support Java Records when present in JVM. (#2201)
* Support Java Records when present in JVM.
Fixes google/gson#1794
Added support in the ReflectionHelper to detect if a class is a record
on the JVM (via reflection), and if so, we will create a special
RecordAdapter to deserialize records, using the canoncial constructor.
The ReflectionTypeAdapterFactory had to be refactored a bit to support
this. The Adapter class inside the factory is now abstract, with
concrete implementations for normal field reflection and for Records.
The common code is in the Adapter, with each implementation
deserializing values into an intermediary object.
For the FieldReflectionAdapter, the intermediary is actually the final
result, and field access is used to write to fields as before. For the
RecordAdapter the intermediary is the Object[] to pass to the Record
constructor.
* Fixed comments from @Marcono1234
Also updated so that we now use the record accessor method to read out
values from a record, so that direct field access is not necessary.
Also added some tests, that should only execute on Java versions with
record support, and be ignored for other JVMs
* Fixed additional comments from @Marcono1234
* Made Adapter in ReflectiveTypeAdapterFactory public
Fix comment from @eamonnmcmanus
2022-10-11 18:13:49 +02:00
|
|
|
|
|
|
|
|
2022-10-22 18:01:56 +02:00
|
|
|
private static RuntimeException createExceptionForRecordReflectionException(
|
Support Java Records when present in JVM. (#2201)
* Support Java Records when present in JVM.
Fixes google/gson#1794
Added support in the ReflectionHelper to detect if a class is a record
on the JVM (via reflection), and if so, we will create a special
RecordAdapter to deserialize records, using the canoncial constructor.
The ReflectionTypeAdapterFactory had to be refactored a bit to support
this. The Adapter class inside the factory is now abstract, with
concrete implementations for normal field reflection and for Records.
The common code is in the Adapter, with each implementation
deserializing values into an intermediary object.
For the FieldReflectionAdapter, the intermediary is actually the final
result, and field access is used to write to fields as before. For the
RecordAdapter the intermediary is the Object[] to pass to the Record
constructor.
* Fixed comments from @Marcono1234
Also updated so that we now use the record accessor method to read out
values from a record, so that direct field access is not necessary.
Also added some tests, that should only execute on Java versions with
record support, and be ignored for other JVMs
* Fixed additional comments from @Marcono1234
* Made Adapter in ReflectiveTypeAdapterFactory public
Fix comment from @eamonnmcmanus
2022-10-11 18:13:49 +02:00
|
|
|
ReflectiveOperationException exception) {
|
2022-10-22 18:01:56 +02:00
|
|
|
throw new RuntimeException("Unexpected ReflectiveOperationException occurred"
|
|
|
|
+ " (Gson " + GsonBuildConfig.VERSION + ")."
|
|
|
|
+ " To support Java records, reflection is utilized to read out information"
|
|
|
|
+ " about records. All these invocations happens after it is established"
|
|
|
|
+ " that records exist in the JVM. This exception is unexpected behavior.",
|
Support Java Records when present in JVM. (#2201)
* Support Java Records when present in JVM.
Fixes google/gson#1794
Added support in the ReflectionHelper to detect if a class is a record
on the JVM (via reflection), and if so, we will create a special
RecordAdapter to deserialize records, using the canoncial constructor.
The ReflectionTypeAdapterFactory had to be refactored a bit to support
this. The Adapter class inside the factory is now abstract, with
concrete implementations for normal field reflection and for Records.
The common code is in the Adapter, with each implementation
deserializing values into an intermediary object.
For the FieldReflectionAdapter, the intermediary is actually the final
result, and field access is used to write to fields as before. For the
RecordAdapter the intermediary is the Object[] to pass to the Record
constructor.
* Fixed comments from @Marcono1234
Also updated so that we now use the record accessor method to read out
values from a record, so that direct field access is not necessary.
Also added some tests, that should only execute on Java versions with
record support, and be ignored for other JVMs
* Fixed additional comments from @Marcono1234
* Made Adapter in ReflectiveTypeAdapterFactory public
Fix comment from @eamonnmcmanus
2022-10-11 18:13:49 +02:00
|
|
|
exception);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Internal abstraction over reflection when Records are supported.
|
|
|
|
*/
|
|
|
|
private abstract static class RecordHelper {
|
|
|
|
abstract boolean isRecord(Class<?> clazz);
|
|
|
|
|
|
|
|
abstract String[] getRecordComponentNames(Class<?> clazz);
|
|
|
|
|
|
|
|
abstract <T> Constructor<T> getCanonicalRecordConstructor(Class<T> raw);
|
|
|
|
|
|
|
|
public abstract Method getAccessor(Class<?> raw, Field field);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static class RecordSupportedHelper extends RecordHelper {
|
|
|
|
private final Method isRecord;
|
|
|
|
private final Method getRecordComponents;
|
|
|
|
private final Method getName;
|
|
|
|
private final Method getType;
|
|
|
|
|
|
|
|
private RecordSupportedHelper() throws NoSuchMethodException {
|
|
|
|
isRecord = Class.class.getMethod("isRecord");
|
|
|
|
getRecordComponents = Class.class.getMethod("getRecordComponents");
|
2022-10-22 18:01:56 +02:00
|
|
|
// Class java.lang.reflect.RecordComponent
|
|
|
|
Class<?> classRecordComponent = getRecordComponents.getReturnType().getComponentType();
|
|
|
|
getName = classRecordComponent.getMethod("getName");
|
|
|
|
getType = classRecordComponent.getMethod("getType");
|
Support Java Records when present in JVM. (#2201)
* Support Java Records when present in JVM.
Fixes google/gson#1794
Added support in the ReflectionHelper to detect if a class is a record
on the JVM (via reflection), and if so, we will create a special
RecordAdapter to deserialize records, using the canoncial constructor.
The ReflectionTypeAdapterFactory had to be refactored a bit to support
this. The Adapter class inside the factory is now abstract, with
concrete implementations for normal field reflection and for Records.
The common code is in the Adapter, with each implementation
deserializing values into an intermediary object.
For the FieldReflectionAdapter, the intermediary is actually the final
result, and field access is used to write to fields as before. For the
RecordAdapter the intermediary is the Object[] to pass to the Record
constructor.
* Fixed comments from @Marcono1234
Also updated so that we now use the record accessor method to read out
values from a record, so that direct field access is not necessary.
Also added some tests, that should only execute on Java versions with
record support, and be ignored for other JVMs
* Fixed additional comments from @Marcono1234
* Made Adapter in ReflectiveTypeAdapterFactory public
Fix comment from @eamonnmcmanus
2022-10-11 18:13:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
boolean isRecord(Class<?> raw) {
|
|
|
|
try {
|
2022-10-12 23:24:36 +02:00
|
|
|
return (boolean) isRecord.invoke(raw);
|
Support Java Records when present in JVM. (#2201)
* Support Java Records when present in JVM.
Fixes google/gson#1794
Added support in the ReflectionHelper to detect if a class is a record
on the JVM (via reflection), and if so, we will create a special
RecordAdapter to deserialize records, using the canoncial constructor.
The ReflectionTypeAdapterFactory had to be refactored a bit to support
this. The Adapter class inside the factory is now abstract, with
concrete implementations for normal field reflection and for Records.
The common code is in the Adapter, with each implementation
deserializing values into an intermediary object.
For the FieldReflectionAdapter, the intermediary is actually the final
result, and field access is used to write to fields as before. For the
RecordAdapter the intermediary is the Object[] to pass to the Record
constructor.
* Fixed comments from @Marcono1234
Also updated so that we now use the record accessor method to read out
values from a record, so that direct field access is not necessary.
Also added some tests, that should only execute on Java versions with
record support, and be ignored for other JVMs
* Fixed additional comments from @Marcono1234
* Made Adapter in ReflectiveTypeAdapterFactory public
Fix comment from @eamonnmcmanus
2022-10-11 18:13:49 +02:00
|
|
|
} catch (ReflectiveOperationException e) {
|
|
|
|
throw createExceptionForRecordReflectionException(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
String[] getRecordComponentNames(Class<?> raw) {
|
|
|
|
try {
|
|
|
|
Object[] recordComponents = (Object[]) getRecordComponents.invoke(raw);
|
|
|
|
String[] componentNames = new String[recordComponents.length];
|
|
|
|
for (int i = 0; i < recordComponents.length; i++) {
|
|
|
|
componentNames[i] = (String) getName.invoke(recordComponents[i]);
|
|
|
|
}
|
|
|
|
return componentNames;
|
|
|
|
} catch (ReflectiveOperationException e) {
|
|
|
|
throw createExceptionForRecordReflectionException(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public <T> Constructor<T> getCanonicalRecordConstructor(Class<T> raw) {
|
|
|
|
try {
|
|
|
|
Object[] recordComponents = (Object[]) getRecordComponents.invoke(raw);
|
|
|
|
Class<?>[] recordComponentTypes = new Class<?>[recordComponents.length];
|
|
|
|
for (int i = 0; i < recordComponents.length; i++) {
|
|
|
|
recordComponentTypes[i] = (Class<?>) getType.invoke(recordComponents[i]);
|
|
|
|
}
|
|
|
|
// Uses getDeclaredConstructor because implicit constructor has same visibility as record and might
|
|
|
|
// therefore not be public
|
|
|
|
return raw.getDeclaredConstructor(recordComponentTypes);
|
|
|
|
} catch (ReflectiveOperationException e) {
|
|
|
|
throw createExceptionForRecordReflectionException(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Method getAccessor(Class<?> raw, Field field) {
|
|
|
|
try {
|
|
|
|
// Records consists of record components, each with a unique name, a corresponding field and accessor method
|
|
|
|
// with the same name. Ref.: https://docs.oracle.com/javase/specs/jls/se17/html/jls-8.html#jls-8.10.3
|
|
|
|
return raw.getMethod(field.getName());
|
|
|
|
} catch (ReflectiveOperationException e) {
|
|
|
|
throw createExceptionForRecordReflectionException(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Instance used when records are not supported
|
|
|
|
*/
|
|
|
|
private static class RecordNotSupportedHelper extends RecordHelper {
|
|
|
|
|
|
|
|
@Override
|
|
|
|
boolean isRecord(Class<?> clazz) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
String[] getRecordComponentNames(Class<?> clazz) {
|
|
|
|
throw new UnsupportedOperationException(
|
|
|
|
"Records are not supported on this JVM, this method should not be called");
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
<T> Constructor<T> getCanonicalRecordConstructor(Class<T> raw) {
|
|
|
|
throw new UnsupportedOperationException(
|
|
|
|
"Records are not supported on this JVM, this method should not be called");
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Method getAccessor(Class<?> raw, Field field) {
|
|
|
|
throw new UnsupportedOperationException(
|
|
|
|
"Records are not supported on this JVM, this method should not be called");
|
|
|
|
}
|
|
|
|
}
|
2021-11-09 16:16:35 +01:00
|
|
|
}
|