可以将一个不完全不可变的集合声明为“final”并将其视为常量吗?

时间:2017-06-02 20:59:39

标签: java

本质上,我在问一个集合是否可以被视为常量,不是因为它在技术上不可能改变它的元素,而是因为它的元素不是要改变的,也不会被改变。执行?假设我声明了一个这样的数组:

package foo;

class Foo
{
    final static String[] SURNAMES = {"Beaufort", "Fitzroy",  
        "MacDonald"};

    // Other code...
}

我知道在这种情况下,数组本身是final但它的元素仍然可以改变。但是,由于我正在编写其余的包,我可以确保它们永远不会。如果它是供其他人使用的,它是大写的并且声明为final会让用户知道它应该被视为这样,我会假设。

我对Java比较陌生,我想知道这样做是不安全还是不受欢迎,如果是这样,为什么会这样,以及我的替代品是什么。

1 个答案:

答案 0 :(得分:3)

你说,

  

我知道在这种情况下,数组本身是final但它的元素   仍然可以改变。但是,因为我正在写其余的   包,我可以确保他们永远不会。如果是有意的话   供其他人使用,它是大写的,并声明final会让   用户知道应该这样对待,我认为。

在这种情况下,它是一个包私有对用户来说是一个更好的信号,不会弄乱它。事实上,他们不能看到或触摸它而不诉诸反射或JNI,或在你的包中创建自己的类(最后一个可以通过密封包来防止)。不要依赖命名约定来强制执行行为。

但这些都不会阻止您自己的代码修改数组元素,可能是偶然的。如果您的代码的正确性取决于它们没有改变,那么您不应该打开可能性,尤其是带有static字段。您无法使用数组执行此操作,但您可以使用真正的 Collection,例如List。因此,请考虑这一点:

class Foo {
    final static List<String> SURNAMES = Collections.unmodifiableList(
            Arrays.asList("Beaufort", "Fitzroy", "MacDonald") );

    // ...
}

一个List - 特别是以这种方式构建的一个 - 具有类似于数组的属性,与数组不同,它可以拒绝修改尝试,就像那个一样。