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

2022-08-31 15:13:39

存在声纳违规:

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

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

但我想知道为什么?


答案 1

它抱怨您存储的数组与调用方持有的数组相同。也就是说,如果调用方随后修改此数组,则存储在对象中的数组(以及对象本身)将发生更改。

解决方案是在对象传递时在对象内创建副本。这称为防御性复制。对集合的后续修改不会影响存储在对象中的数组。

在返回集合时(例如,在相应的调用中),通常执行此操作也是一种很好的做法。否则,接收方可能会执行修改并影响存储的实例。getMyArray()

请注意,这显然适用于所有可变集合(实际上也适用于所有可变对象),而不仅仅是数组。另请注意,这会对性能产生影响,需要与其他问题一起进行评估。


答案 2

这被称为防御性复制。关于这个主题的一篇不错的文章是Brian Goetz的“到底是谁的对象?”,它讨论了getters和setters的值和参考语义之间的差异。

基本上,引用语义(没有副本)的风险是,您错误地认为自己拥有数组,并且在修改它时,还会修改具有数组别名的其他结构。您可以在线找到许多有关防御性复制以及与对象混叠相关的问题的信息。


推荐