PMD在Sun Security规则集中有一个名为ArrayIsStoredDirectly的规则:
接收数组的构造函数和方法应克隆对象并存储副本。这可以防止用户将来的更改影响内部功能。
以下是他们的例子:
public class Foo {
private String [] x;
public void foo (String [] param) {
// Don't do this, make a copy of the array at least
this.x=param;
}
}
我认为我完全不了解这条规则背后的原因。是因为传递的数组中的值可以在其他地方更改吗?传递Collection与传递数组之间有什么不同吗?
答案 0 :(得分:12)
问题是调用者可能会保留它传递的数组参数的副本,然后可以更改其内容。如果对象是安全关键的,并且调用是由不受信任的代码进行的,那么您就会遇到安全漏洞。
在此上下文中,传递集合并保存它而不复制它也可能存在安全风险。 (我不知道是否有PMD规则告诉你这个。)
在这两种情况下,解决风险的方法(如果是真的)是将属性设置为参数数组或集合的副本。另一方面,如果您知道调用者始终是可信代码,那么副本就是浪费时间,更好的解决方案是告诉PMD对该特定方法保持沉默。
答案 1 :(得分:3)
传递集合或数组之间没有区别:在这两种情况下,发送方和接收方都可以修改数据结构的内容。这是一个例子:
// ... in some method
Foo myfoo = new Foo();
String[] array = {"One", "Two", "Three"};
myfoo.foo(array); // now the Foo instance gets {"One", "Two", "Three"}
array[1] = "Changed"; // now the internal field x in myfoo is {"One", "Changed", "Three"}
如果您不想要此行为,则必须遵循此PMD规则,在Foo中克隆该数组并存储对该克隆的引用。这样你就可以确保没有其他类拥有对你的内部数组的引用(除非我们暂时忘记反射,除非我们不在另一个方法中返回这个内部数组......)
答案 2 :(得分:1)
我认为数组的主要问题是你无法控制对它的访问。
但是使用对象,您可以隐藏成员之后的成员,可以控制将要设置的内容。我认为同样适用于收藏集,因为您需要致电add()
而toArray()
会返回副本。