声纳违规:安全阵列直接存储

时间:2015-10-26 13:03:19

标签: java sonarqube defensive-copy

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

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

2 个答案:

答案 0 :(得分:1)

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

public static string Stringify(this byte[] b) { return Encoding.ASCII.GetString(b); }

Sonar抱怨,因为this.selectFields = Arrays.copyOf(selectFields, selectedFields.length)数组可以修改所有者BeanResultSetHandler

答案 1 :(得分: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报告的所有此类问题。

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