Findbugs通过参数或clone()分配字节数组值

时间:2016-06-28 09:07:23

标签: java arrays bytearray findbugs

所以例如我有这个构造函数

public Example(byte[] bytes) {
    this.bytes = bytes;
}

在运行FindBugs之后,它会说我应该考虑克隆它...所以我尝试了它并且它消除了警告。

public Example(byte[] bytes) {
    this.bytes = bytes.clone();
}

但是,我想知道这种变化是否有任何影响或负面影响。根据我的理解,它也适用于所有数组,而不仅仅是byte []。

由于

3 个答案:

答案 0 :(得分:3)

可能的错误是,如果你在实例中重用数组,你将它与调用代码耦合,即对数组所做的每次更改都会产生副作用。

示例:

char[] chars = new char[]{ 'a', 'b', 'c', ..., 'z' };
Alphabet lower = new Alphabet( chars );

for( int i = 0; i < chars.length; i++ ) {
  chars[i] = Character.toUpperCase( chars[i] );
}
Alphabet upper = new Alphabet( chars );

如果数组在Alphabet内重用(即未克隆),您可能会认为lower处理小写字符,而它实际上正在使用其元素已被其替换的数组大写反驳部分。

因此,在大多数情况下,创建阵列的副本更安全,例如通过在其上调用clone()(还有其他方法)。

这样做的缺点是内存使用量增加(当然)和执行复制的一些性能成本 - 对于一些小型阵列来说,这两者都可以忽略不计,但是当阵列的大小和/或数量增加时,这两者都会增加。

另一个缺点可能是调用代码可能期望共享数组并且创建克隆可能会破坏它。你也必须检查它。

答案 1 :(得分:1)

这是一种非常普遍的情况 - 当你创建一个依赖于某些&#34;外部&#34;数组或列表 - 该对象应该只是重用现有的引用;或者您是否需要创建该输入数据的副本?!

重用意味着:您不会在复制操作上花费CPU周期;显然,你也重新使用记忆(一份东西,而不是两份,三份......)

另一方面:当你保留引用时,有人会更新那些&#34;外部&#34;事物......拥有该引用的所有对象也可能受到影响。

从这个意义上说:你应该平衡这两个选项,主要是基于什么是最好的&#34;从设计的角度来看。一般来说,现在很多人都试图实现不可变的类/对象。含义:在创作时,&#34;内容&#34;一个物体永远不会改变;换句话说:如果你想要不可改变,你必须转向&#34;防御性复制&#34;。但是从那里可以获得很多东西。

答案 2 :(得分:0)

这个想法是采取防御性副本,以便对数组的后续更新不会写入Example对象。它还有助于垃圾收集,因为您没有持有对数组的引用。

就影响而言,您可能会使用更多内存,因为最终可能会将数组存储两次。