Нарушение сонара:Security-Array хранится напрямую

Я пытаюсь изменить свои коды в моем приложении с помощью 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 ответа

Вы должны клонировать массив перед его сохранением:

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

Сонар жалуется, потому что от BeanResultSetHandler массив, владельцем которого является caller может быть изменено.

Сонар говорит вам, что вы не копируете 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

Является ли это реальной проблемой, зависит IMHO, если вызывающая сторона, вероятно, будет использовать пользовательский массив, который она будет склонна изменить после вызова конструктора. Если во всех реальных случаях аргумент равен нулю или является результатом какого-то 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.

Лично я склонен применять такие идиомы только через границы модулей, например, в методах, используемых для предоставления сервисов другим модулям. Тогда внутри модулей я не использую защитную копию и вместо этого полагаюсь на юнит-тесты.

Другие вопросы по тегам