I'm trying to create a generic builder for value classes. You know those dumb classes full of getter and setters.
The goal is to be able to use it like this:
MyValueObject myvalueObject = new GenericBuilder<MyValueObject>(MyValueObject.class)
.with("someIntegerProperty", 12)
.build();
Here's my attempt so far using reflection:
public class GenericBuilder<T> {
private T bean;
private Class<T> clazz;
public GenericBuilder(Class<T> clazz) {
this.clazz = clazz;
Constructor<?> constructor = null;
try {
constructor = Class.forName(clazz.getCanonicalName()).getConstructor();
bean = (T) constructor.newInstance();
} catch (NoSuchMethodException | ClassNotFoundException | IllegalAccessException | InvocationTargetException | InstantiationException e) {
e.printStackTrace();
}
}
public <S> GenericBuilder<T> with(String propertyName, S value) {
Method method;
try {
method = Class.forName(clazz.getCanonicalName())
.getMethod("set" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1), Object.class);
method.invoke(bean, (S) value);
} catch (NoSuchMethodException | ClassNotFoundException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
return this;
}
public T build() {
return bean;
}
}
However the method invocation fails with a NoSuchMethodException
because the determined parameter type at runtime is Object
instead of the correct type. This is due to type erasure.
I know that I can get the actual parameter type with method.getParameterTypes()[0]
, but I cannot use it to cast the value
like this
method.invoke(bean, (method.getParameterTypes()[0]) value); //compiler error
How can I fix this?
Aucun commentaire:
Enregistrer un commentaire