最终字符串的最终数组是否仍然可变?

时间:2015-04-15 16:32:10

标签: java arrays string final

假设我有一个数组

public static final String[] fooArray ={ Foo.a, Foo.b, Foo.c };

其中Foo.a b和c是静态最终字符串。

我是否还可以执行fooArray[0] = "taco";之类的操作,最后以{ taco, Foo.b, Foo.c }作为fooArray的内容?

如果是这样,是否会将数组设为私有,并且使用Arrays.copyOf创建数组副本的getter可以解决此问题?

5 个答案:

答案 0 :(得分:8)

final适用于数组引用,而不适用于其条目。不同的字符串仍然可以写入其条目。

  

如果是这样,是否会将数组设为私有,并且使用Arrays.copyOf创建数组副本的getter可以解决此问题?

是的,防御性副本是处理此问题的一种相当标准的方式。

或者,根据您的概述,您根本不需要拥有阵列,只需要一个看起来像这样的吸气剂:

public String[] getFooArray() {
    return new String[] { Foo.a, Foo.b, Foo.c };
}

as jtahlborn commented,使用不可修改的List<String>

public static final List<String> fooArray;
static {
    List<String> a = new ArrayList<>();
    Collections.addAll(a, Foo.a, Foo.b, Foo.c);
    fooArray = Collections.unmodifiableList(a);
}
// (There's probably some really nifty Java8 way to do that as a one-liner...

答案 1 :(得分:4)

final数组意味着您无法重新分配数组。

所以你做不到:fooArray = new String[]{...};

但是你可以改变数组内部的内容。这就是说:“你不能改变盒子,但你可以把盒子里的苹果变成橘子。”框保持不变,并且是最终的,但您已经有效地更改了内容。


话虽这么说,如果你封装了类,那么你可以在需要时克隆数组。

目前许多类都使用它,例如String#toCharArrayEnum#values,其中更改数组的内容包括最终对象的完整性。

答案 2 :(得分:2)

final - 修饰符只会阻止更改fooArray - 引用,而不会更改数组本身的内容。将其设为私有并使getter返回副本将隐藏原始数组,并且对返回的数组所做的任何更改都只会影响副本。但是,仍然可以通过反射修改原始内容,但如果您的意图是仅防止意外修改原始数组,那么这将起作用。

答案 3 :(得分:0)

休息已经回答了最后一口井。只是对另一部分的建议 - 而不是实现一个getter来完成整个数组的复制,如果你的场景允许,最好有一个getArrayElement(int position),你只返回一个数组元素而不是整个数组 - 复制阵列很贵。

答案 4 :(得分:0)

您可以创建一个返回不可变值的可变副本的getter。 如果使用数组副本,副本中的值仍将是最终值。

public class HelloWorld{
    public static void main(String []args){
    System.out.println("Hello World");
    final int b = 5;
    int c = b; // Because of c being mutable we can now change this copy
    c = 7;
    System.out.println(c);
 }
}

...一些psudo代码 - &gt;将iterable复制为可变形式。

public collection<int>(final collection<final int> finalCollection )
    collection nonFinalCollection = new collention();
    for(k : finalCollention){collection.add((int) k)}
    return(collection)