假设我有一个数组
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可以解决此问题?
答案 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#toCharArray
和Enum#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)