修改 public 静态最终数组

modifying a public static final array

在设计一个小的 API 时,我正要编写一个引用字符串数组的静态值: public static final String[] KEYS={"a","b","c"} 我发现这在 Joshua Bloch 的 'Effective Java' 项目 14 中被标记为 'security hole',他建议作为替代方案,声明数组 'private' 并提供 public getter returns 一个不可修改的列表:

return Collections.unmodifiableList(Arrays.asList(KEYS))

我只是不明白为什么这是必要的,初始语句中的数组被声明为最终的,即使它 public,并且它的元素是不可变的,如何从外部代码修改它?

最终表示

You can't change the Basket. Still you can change the fruits inside.

Basket 是您的 Array 实例。水果是你里面的钥匙。

在第一种情况下,我可以从代码的其他地方做到

ClassName.KEYS[2] ="MyOwnValue";

但不可修改列表是不能修改的

尝试阅读:Why final instance class variable in Java?

数组不是不可变的。

你还可以写:

KEYS[0] = "d";

没有任何问题。 final 只是意味着你不能写:

KEYS = new String[]{"d"};

即您不能为变量 KEYS.

分配新值

虽然数组引用本身是不可变的(您不能用对另一个数组的引用替换它)并且字符串本身也是不可变的,但仍然可以编写

KEYS[0] = "new Key";

一个复合对象(数组、SetList 等)是 final 并不意味着它的组成对象不会被改变——你仍然可以改变组成对象。 final 对于复合对象仅仅意味着它的引用不能被改变。

对于您的情况,无法更改 KEYS 的值,但可以更改 KEYS[0] 等。