声纳违规:安全 - 数组直接存储

Jun*_*Liu 60 java sonarqube

有声纳违规:

声纳违规:安全 - 数组直接存储

public void setMyArray(String[] myArray) { 
  this.myArray = myArray; 
} 
Run Code Online (Sandbox Code Playgroud)

解:

public void setMyArray(String[] newMyArray) { 
  if(newMyArray == null) { 
    this.myArray = new String[0]; 
  } else { 
   this.myArray = Arrays.copyOf(newMyArray, newMyArray.length); 
  } 
}
Run Code Online (Sandbox Code Playgroud)

但我想知道为什么?

Bri*_*new 51

它抱怨你存储的数组与调用者持有的数组相同.也就是说,如果调用者随后修改了这个数组,那么存储在对象中的数组(以及对象本身)将会改变.

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

通常在返回集合时执行此操作(例如在相应的getMyArray()调用中)也是一种好习惯.否则,接收器可以执行修改并影响存储的实例.

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

  • 这是一个设计决定.但我认为了解*谁拥有这些数据,以及如何(如果有必要)通知持有它的对象已经改变了,这一点很重要.与没有防御性复制的传递集合密切相关的组件集是非常合理的.但在某些时候,你需要保护自己的边界(例如插入第三个pary或客户代码) (2认同)
  • 此外,我不明白为什么它只是显示数组.因为,在bean中我们将有自定义对象和相同的问题(调用者将持有相同的副本,如果他更改,它将在内部影响)可以发生,但它不抱怨. (2认同)

ewe*_*nli 21

它被称为防御性复制.关于这个主题的一篇很好的文章是"无论如何,它谁的对象?" 作者:Brian Goetz,讨论了getter和setter的值和引用语义之间的区别.

基本上,引用语义(没有副本)的风险是你错误地认为你拥有数组,当你修改它时,你也修改了其他具有数组别名的结构.您可以在线找到有关防御性复制和与对象别名相关的问题的许多信息.


Jor*_*sys 12

我遇到过同样的问题:

安全性 - 数组直接存储用户提供的数组 'palomitas'直接存储.

我原来的方法:

public void setCheck(boolean[] palomitas) {
        this.check=palomitas;
    }
Run Code Online (Sandbox Code Playgroud)

固定转向:

public void setCheck(boolean[] palomitas) { 
      if(palomitas == null) { 
        this.check = new boolean[0]; 
      } else { 
       this.check = Arrays.copyOf(palomitas, palomitas.length); 
      } 
}
Run Code Online (Sandbox Code Playgroud)

其他例子:

安全性 - 数组直接存储用户提供的数组

private String[] arrString;

    public ListaJorgeAdapter(String[] stringArg) {      
        arrString = stringArg;
    }
Run Code Online (Sandbox Code Playgroud)

固定:

public ListaJorgeAdapter(String[] stringArg) {  
    if(stringArg == null) { 
      this.arrString = new String[0]; 
    } else { 
      this.arrString = Arrays.copyOf(stringArg, stringArg.length); 
    } 
}
Run Code Online (Sandbox Code Playgroud)