versions used (SonarLint : SonarSource : 5.0.1.33703)
Exemple :
public final class Exemple {
private Integer i;
private Integer j;
public void init(final Map<String, Integer> myMap) throws IllegalAccessException {
final Field[] fields = Exemple.class.getDeclaredFields();
for(final Field f : fields){
if(f.getType().equals(Integer.TYPE)) {
final Integer value = myMap.get(f.getName());
f.set(this, value);
}
}
}
}
I have a “java:S3011” on line f.set(this, value);
But I do not increase accessibility of classes, methods, or fields. I update directly a field, but it is on “this” object, so that does not violate the encapsulation principle.
Thank you for the report. Using reflection to set fields on objects of the current class does indeed not circumvent accessibility or violate the encapsulation principle, so the rule is misleading in that regard.
However, if you look at the comment in the code example, it points out a more valid reason for not setting fields using reflection: It bypasses the setter and any validation logic that might be happening within it. Since setting fields using reflection is usually something you do for deserialization or similar purposes, you’d usually want validation to happen, so you should be calling the setters using reflection rather than setting the fields directly.
That said, this only makes sense if all your fields have setters. And it’s kind of irrelevant when none of the setters do any validation. For classes like the one in your example where there are no setters, this reasoning does not really apply. So it would be better if the rule only raised an issue for fields being set on the current object if all fields have setters and at least one of them does something besides just set the field.
I’ve created a ticket to apply this change to the rule and to rephrase the rule description to make it less misleading.