0

我正在尝试使用声纳更改我的应用程序中的代码。如何解决它,为什么?谢谢。

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();
}
4

2 回答 2

1

您必须在存储之前克隆数组:

this.selectFields = Arrays.copyOf(selectFields, selectedFields.length)

声纳抱怨,因为可以从BeanResultSetHandler阵列caller修改所有者。

于 2015-10-26T13:18:57.727 回答
0

Sonar 告诉您,您不是在复制selectedFields数组,而只是存储对该数组的引用。因此,如果调用者稍后要修改数组,它也会修改 BeanResultSetHandler 对象的“内容”,例如使用以下代码:

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

这是否是一个真正的问题取决于恕我直言,如果调用者可能使用自定义数组,她会在调用构造函数后试图修改该数组。如果在所有实际情况下,参数为 null 或某些 Class.getFields() 的结果,我不会太在意它。

“防御性副本”习惯用法是永远不要存储对可变对象或数组的引用,而是在有疑问时始终克隆,在您的情况下克隆数组:

public BeanResultSetHandler(Class<T> type, Object[] selectedFields) {
    this.clas = type;
    if (selectedFields == null)
        this.selectFields = this.clas.getFields();
    else
        this.selectFields = selectedFields.clone();
}

问题是克隆会产生性能开销,当这种方法被推广时(例如,当从对象返回某些东西时),将会执行大量无用的克隆。所以我不会开始尝试纠正 Sonar 报告的所有此类问题。

就我个人而言,我倾向于仅在模块边界上应用这些惯用语,例如在用于将服务公开给其他模块的方法中。然后在模块内部,我不使用防御性副本,而是依赖单元测试。

于 2015-10-26T13:21:57.803 回答