有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java为什么要将私有字段的副本声明为“final”`

约书亚·布洛赫在书中写道:

Note that a nonzero-length array is always mutable, so it is wrong for a class to have a public static final array field, or an accessor that returns such a field. If a class has such a field or accessor, clients will be able to modify the contents of the array. This is a frequent source of security holes:

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

Beware of the fact that many IDEs generate accessors that return references to private array fields, resulting in exactly this problem. There are two ways to fix the problem. You can make the public array private and add a public immutable list:

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

Alternatively, you can make the array private and add a public method that returns a copy of a private array:

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

我的问题是:

  • 如果只是一个副本,为什么还要麻烦返回final变量呢


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


共 (2) 个答案

  1. # 1 楼答案

    这并不是返回final对象,而是将该方法声明为不可重写。没有final对象,只有最终变量(引用或原语)、最终方法和最终类

  2. # 2 楼答案

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

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