Reputation: 213
I m trying to change my codes in my application with using Sonar. How to fix it and why? Thanks.
public class BeanResultSetHandler<T> extends BasicResultSetHandler<T> {
T instance;
Class<T> clas;
Object[] selectFields;
/**
* Constructor
*/
**
public BeanResultSetHandler(Class<T> type, Object[] selectedFields) {
this.clas = type;
this.selectFields = selectedFields;
if (selectedFields == null)
this.selectFields = this.clas.getFields();
}
Upvotes: 0
Views: 135
Reputation: 589
Sonar tells you that you are not copying the selectedFields
array, but merely storing a reference to this array. As a consequence, if the caller is to later modify the array, it will modify the "content" of the BeanResultSetHandler object as well, e.g. with the following code:
h = new BeanResultSetHandler(MyClass.class, myFieldsArray);
myFieldsArray[0] = null; // now t.selectFields[0] also is null
myFieldsArray[0] = someObject; // now t.selectFields[0] also references someObject
Whether this is a real problem depends IMHO if the caller is likely to use a custom array that she would be tempted to modify after the call to the constructor. If in all real cases the argument is null or the result of some Class.getFields() I would not bother with it too much.
The "defensive copy" idiom is to never store a reference to a mutable object or array, but to always clone in case of doubt, in your case cloning the array:
public BeanResultSetHandler(Class<T> type, Object[] selectedFields) {
this.clas = type;
if (selectedFields == null)
this.selectFields = this.clas.getFields();
else
this.selectFields = selectedFields.clone();
}
The problem is that cloning can incur performance overhead, and when this approach is generalized (e.g. also when returning something from the objects) then an awful lot of useless clones will be performed. So I wouldn't start trying to correct all such issues reported by Sonar.
Personally, I tend to apply such idioms only over module boundaries, e.g. in the methods used to expose services to other modules. Then inside modules I do not use defensive copy and rely on unit tests instead.
Upvotes: 0
Reputation: 1680
You have to clone the array before storing it:
this.selectFields = Arrays.copyOf(selectFields, selectedFields.length)
Sonar complains because from BeanResultSetHandler
array which owner is caller
could be modified.
Upvotes: 1