Since I may not be able to enforce the declaration of a static field in the deriving classes' definition, I will go by storing a map of attribute sets and class descriptions in the definition of the Entity
class described above and making sure that the set of attributes for a derived class is initialized in the Entity
constructor.
As an example:
public class Entity
{
private final static Map<Class<? extends Entity>, Set<String>> attributes = new HashMap<Class<? extends Entity>, Set<String>>();
public static void populateAttributes(Class<? extends Entity> derivedClass)
{
//initialize the set of attributes for the derived class and
//add it to attributes map with "derivedClass" as key
}
static
{
populateAttributes(Entity.class);
}
public Entity()
{
//calling this.getClass() returns the object's actual (derived) class(*)
if(!attributes.containsKey(this.getClass())
populateAttributes(this.getClass());
}
//rest of class definition (including getAttributes method)
}
public class Customer extends Entity
{
@Attribute
String someAttribute; //will be processed automatically
}
The cost of getting an Entity
s attributes is reduced from parsing all class attributes and creating a new set to hold them to a check-and-retrieve operation on a Map
which should be quite small when using a HashMap
.
The cost of creating an Entity
instance is increased by a check done to the attributes Map
(fast on HashMap
s). The cost of initializing the attributes
set for a given class is negligible, as it is done only once per derivate class type.
Considering that the attributes are requested at least once per class instance on 90% or more of the occasions, this should give better overall performance than the initial solution described in the question.
(*)calling this.getClass()
in a base class instance method will return the object's actual class. If the object has been initialized as a derived class instance, the derived class' description (Class
object) will be returned. A question about this has already been asked and answered here: Which class does getClass() report inside a constructor of a base class.