For some reason, I need to cache entries of classes and their field or field name using reflection.
private static final Map<Class<?>, String> ID_ATTRIBUTE_NAMES = new WeakHashMap<>();
private static String findIdAttributeName(final Class<?> clazz) {
Objects.requireNonNull(clazz, "clazz is null");
for (Class<?> current = clazz; current != null; current = current.getSuperclass()) {
for (final Field field : current.getDeclaredFields()) {
if (field.getAnnotation(Id.class) != null) {
return field.getName();
}
if (field.getAnnotation(EmbeddedId.class) != null) {
return field.getName();
}
}
}
throw new RuntimeException("unable to find an id attribute from " + clazz);
}
private static String idAttributeName(final Class<?> clazz) {
Objects.requireNonNull(clazz, "clazz is null");
return ID_ATTRIBUTE_NAMES.computeIfAbsent(clazz, BaseMappedHelper::findIdAttributeName);
}
The reason that I didn't define the map as Map<Class<?>, Field> is that a Field instance might strongly refer the its declaring class.
Is there any other way using other than using the field name of String?
You can use Apache or Spring BeanUtils (https://commons.apache.org/proper/commons-beanutils/) that is optimized with cache.
Maybe you need BeanMap to interacte with your objects as map. https://commons.apache.org/proper/commons-collections/javadocs/api-3.2.2/org/apache/commons/collections/BeanMap.html
But you don't need a weak reference because number of fields is not so huge.