修改一个公共静态不可变数组

7
在设计一个小型API时,我打算写一个静态值,它引用了一个字符串数组:public static final String[] KEYS={"a","b","c"}。我发现这在Joshua Bloch的《Effective Java》第14条中被标记为“安全漏洞”。他提出了一种替代方案,即声明该数组为“private”,并提供一个公共getter,返回一个不可修改的列表:
return Collections.unmodifiableList(Arrays.asList(KEYS))

我不明白为什么需要这样做,初始语句中的数组虽然是公共的,但已经声明为final,而且它的元素也是不可变的,如何能从外部代码修改它呢?

4个回答

12

数组并非不可变。

你仍然可以编写:

KEYS[0] = "d";

没有任何问题。 final只是表示您不能编写:

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

也就是说,您不能对变量KEYS赋一个新值。


1
因为解释了 final,所以我点了赞,似乎很多人不理解这个关键字。 - Manu

5

final的意思是最终的。

你不能改变Basket。但是你可以改变里面的水果。

Basket是你的数组实例。Fruits是你内部的键。

在第一种情况下,我可以从代码的其他地方执行:

ClassName.KEYS[2] ="MyOwnValue";

但是当它是不可修改的列表时,您无法修改它。

阅读以下内容:为什么Java中有final实例类变量?


1
很好的比喻,我喜欢它 :) - Olivier Grégoire

0

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

KEYS[0] = "new Key";

0

一个复合对象(数组,SetList等)被声明为final并不意味着其组成部分对象不会被更改 - 你仍然可以更改组成部分对象。对于复合对象,final只是意味着它的引用不能被更改。

对于你的情况,KEYS的值不能被更改,但是KEYS[0]等可以被更改。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接