4

Efficient Java Joshua Bloch 中写道:

请注意,非零长度数组始终是可变的,因此类具有公共静态最终数组字段或返回此类字段的访问器是错误的。如果一个类有这样的字段或访问器,客户端将能够修改数组的内容。这是安全漏洞的常见来源:

// Potential security hole!
public static final Thing[] VALUES = { ... };

请注意,许多 IDE 生成的访问器会返回对私有数组字段的引用,从而导致了这个问题。有两种方法可以解决问题。您可以将公共数组设为私有并添加一个公共不可变列表:

private static final Thing[] PRIVATE_VALUES = { ... };
public static final List<Thing> VALUES =
Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES));

或者,您可以将数组设为私有并添加一个返回私有数组副本的公共方法:

private static final Thing[] PRIVATE_VALUES = { ... };
public static final Thing[] values() {
    return PRIVATE_VALUES.clone();
}

我的问题是:

  • 为什么要返回一个final变量 - 如果它只是一个副本?


毕竟,如果用户想要修改它(供她/他自己使用),我们实际上是在强迫她/他创建另一个非最终副本,这是没有意义的。

4

2 回答 2

6

Arrays.asList包装原始数组。它不会复制数据。Collections.unmodifiableList还包装原始列表而不是复制数据。

这就是您返回unmodifiableList包装器的原因,否则,对返回的列表所做的更改Arrays.asList将写入原始私有数组。

于 2013-10-24T21:42:29.137 回答
5

这不是返回一个final对象——它只是将方法声明为不可覆盖。没有final对象之类的东西——只有最终变量(引用或原语)、最终方法和最终类。

于 2013-10-24T21:32:53.460 回答