在设计一个小API时,我打算编写一个引用String数组的静态值:
public static final String[] KEYS={"a","b","c"}
我发现这在Joshua Bloch的“Effective Java”第14项中被标记为“安全漏洞”,他建议作为替代方案,声明te array“private”并提供返回不可修改列表的公共getter:
return Collections.unmodifiableList(Arrays.asList(KEYS))
我只是不明白为什么这是必要的,初始语句中的数组被声明为final,即使它是公共的,它的元素是不可变的,怎么可以从外部代码修改?
答案 0 :(得分:8)
数组不是不可变的。
你仍然可以写:
KEYS[0] = "d";
没有任何问题。
final
只是意味着你不能写:
KEYS = new String[]{"d"};
即。您无法为变量KEYS
分配新值。
答案 1 :(得分:4)
final 表示
你不能改变篮子。你仍然可以改变里面的果实。
Basket是您的Array实例。水果是你内心的关键。
在第一种情况下,从代码中的其他地方,我可以做到
ClassName.KEYS[2] ="MyOwnValue";
但是当它是不可修改的列表时你无法修改。
答案 2 :(得分:0)
虽然数组引用本身是不可变的(你不能用对另一个数组的引用替换它)而且字符串本身也是不可变的,所以仍然可以编写
KEYS[0] = "new Key";
答案 3 :(得分:0)
复合对象(数组,Set
,List
等)final
并不意味着它的组成对象不会被更改 - 您仍然可以更改组成对象。复合对象的final
仅表示无法更改其引用。
对于您的情况,KEYS
的值无法更改,但KEYS[0]
等可以更改。