Sonar Violation: Security - Массив хранится напрямую
Нарушение сонара:
Sonar Violation: Security - Массив хранится напрямую
public void setMyArray(String[] myArray) {
this.myArray = myArray;
}
Решение:
public void setMyArray(String[] newMyArray) {
if(newMyArray == null) {
this.myArray = new String[0];
} else {
this.myArray = Arrays.copyOf(newMyArray, newMyArray.length);
}
}
Но мне интересно, почему?
7 ответов
Он жалуется на то, что массив, который вы храните, - это тот же массив, который хранится вызывающей стороной. То есть, если вызывающая сторона впоследствии модифицирует этот массив, массив, сохраненный в объекте (и, следовательно, в самом объекте), изменится.
Решение состоит в том, чтобы сделать копию внутри объекта, когда он будет передан. Это называется защитным копированием. Последующая модификация коллекции не повлияет на массив, хранящийся в объекте.
Это также хорошая практика, чтобы обычно делать это при возврате коллекции (например, в соответствующем getMyArray()
вызов). В противном случае получатель может выполнить модификацию и повлиять на сохраненный экземпляр.
Обратите внимание, что это очевидно относится ко всем изменяемым коллекциям (и фактически ко всем изменяемым объектам), а не только к массивам. Также обратите внимание, что это оказывает влияние на производительность, которое необходимо оценивать наряду с другими проблемами.
Это называется защитным копированием. Хорошая статья на эту тему "Чей это объект?" Брайан Гетц, который обсуждает разницу между значением и ссылочной семантикой для геттеров и сеттеров.
По сути, риск со ссылочной семантикой (без копии) заключается в том, что вы ошибочно думаете, что владеете массивом, и когда вы изменяете его, вы также изменяете другие структуры, имеющие псевдонимы для массива. Вы можете найти много информации о защитном копировании и проблемах, связанных с наложением объектов в Интернете.
У меня была такая же проблема:
Безопасность - Массив хранится напрямую. Предоставленный пользователем массив 'palomitas' сохраняется напрямую.
мой оригинальный метод:
public void setCheck(boolean[] palomitas) {
this.check=palomitas;
}
исправлено:
public void setCheck(boolean[] palomitas) {
if(palomitas == null) {
this.check = new boolean[0];
} else {
this.check = Arrays.copyOf(palomitas, palomitas.length);
}
}
Другой пример:
Безопасность - массив хранится напрямую. Предоставленный пользователем массив
private String[] arrString;
public ListaJorgeAdapter(String[] stringArg) {
arrString = stringArg;
}
Исправлена:
public ListaJorgeAdapter(String[] stringArg) {
if(stringArg == null) {
this.arrString = new String[0];
} else {
this.arrString = Arrays.copyOf(stringArg, stringArg.length);
}
}
Чтобы устранить их, вы должны клонировать массив перед его сохранением / возвратом, как показано в следующей реализации класса, чтобы никто не мог изменить или получить исходные данные вашего класса, а только их копию.
public byte[] getarrString() {
return arrString.clone();
}
/**
* @param arrStringthe arrString to set
*/
public void arrString(byte[] arrString) {
this.arrString= arrString.clone();
}
Я использовал это так, и теперь я не получаю никакого нарушения SONAR...
Это проще, чем все это. Вам нужно только переименовать параметр метода во что-нибудь еще, чтобы избежать нарушений сонара.
http://osdir.com/ml/java-sonar-general/2012-01/msg00223.html
public void setInventoryClassId(String[] newInventoryClassId)
{
if(newInventoryClassId == null)
{
this.inventoryClassId = new String[0];
}
else
{
this.inventoryClassId = Arrays.copyOf(newInventoryClassId, newInventoryClassId.length);
}
}
Путь к оборонительной реализации может сэкономить вам много времени. В Гуаве вы получаете еще одно хорошее решение для достижения цели: ImmutableCollections
http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained
Есть определенные случаи, когда это дизайнерское решение и не пропущено. В этих случаях вам необходимо изменить правила сонара, чтобы исключить его, чтобы он не отображал такие проблемы в отчете.