I have a method with the signature public void setFoo(int newFoo) in a model I'm writing. I'm using the following code to call it from within my controller:
protected void setModelProperty(String propertyName, Object newValue) {
for (AbstractModel model: registeredModels) {
try {
Method method = model.getClass().
getMethod("set"+propertyName, new Class[] {
newValue.getClass()
}
);
method.invoke(model, newValue);
} catch (Exception ex) {
// Handle exception.
System.err.println(ex.toString());
}
}
}
Calling this method like controller.setModelProperty("Foo",5); results in an exception being thrown: java.lang.NoSuchMethodException: foo.bar.models.FooModel.setFoo(java.lang.Integer) -- it looks like the int is being boxed as an Integer, which doesn't match the signature of setFoo.
Is there any way to convince this reflection code to pass 5 (or whatever int I pass in) as an Integer, without the boxing? Or do I have to create public void setFoo(Integer newFoo) in my model and unbox explicitly, then call the original setFoo?
You could specialise your setModelProperty for any primitives you expect to be used with:
protected void setModelProperty(String propertyName, int newValue) { /* ... */ }
Alternatively, you could use instanceof on newValue to check for boxed primitives:
Class[] classes;
if (newValue instanceof Integer) {
classes = new Class[] { int.class };
} else if (newValue instanceof Double) {
/* etc...*/
} else {
classes = new Class[] {newValue.getClass() };
}
Or finally, if you have the source for setFoo, you could change it to take a boxed Integer instead of an int - the overhead is usually negligible.
Is there any way to convince this reflection code to pass 5 (or whatever int I pass in) as an Integer, without the boxing?
Not while your method signature says Object newValue, because an int can never be an Object. A way to keep the method generic would be to have callers pass in the type explicitly, i.e.:
protected void setModelProperty(String propertyName, Object newValue, Class type) {
Alternatively, you could test the type of newValue to see if it's a primitive wrapper and in that case look for both the primitive and the wrapped version of the method. However, that won't work when the user passes in a null. Actually, the method won't work at all in that case...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With