最终字符串的最终数组是否仍然可变?
Is a final array of final strings still mutable?
假设我有一个数组
public static final String[] fooArray ={ Foo.a, Foo.b, Foo.c };
其中 Foo.a b 和 c 是静态最终字符串。
我还能做类似 fooArray[0] = "taco";
的事情并以 { taco, Foo.b, Foo.c }
作为 fooArray 的内容结束吗?
如果是这样,是否可以将数组设为私有,并使用 getter 使用 Arrays.copyOf
制作数组副本来解决此问题?
是的。
A final
数组意味着您不能重新分配数组。
所以你不能这样做:fooArray = new String[]{...};
。
但是您可以更改数组中的内容。这是这样说的效果: "You can't change the box, but you can change the apples inside the box to be oranges." 框保持不变,并且是最终的,但是您实际上已经更改了内容。
也就是说,如果封装 class,那么您可以在需要时克隆数组。
许多 classes 目前都采用这种方法,例如 String#toCharArray
and Enum#values
,其中更改数组的内容包括最终对象的完整性。
final
适用于数组引用,而不是其条目。仍然可以将不同的字符串写入其条目。
If so, would making the array private, and having a getter that makes a copy of the array using Arrays.copyOf solve this issue?
是的,防御性副本是处理此问题的一种相当标准的方法。
或者,鉴于您所概述的内容,您根本不需要数组,只需 getter 如下所示:
public String[] getFooArray() {
return new String[] { Foo.a, Foo.b, Foo.c };
}
或,使用不可修改的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...
final
-修饰符只会阻止更改fooArray
-引用,而不是数组本身的内容。将其设为私有并让 getter 返回副本会隐藏原始数组,对返回数组所做的任何更改只会影响副本。但是,仍然可以通过反射修改原始数组,但如果您的目的只是为了防止意外修改原始数组,那是可行的。
关于最后一口井的其他人已经回答了。只是对另一部分的建议 - 而不是实现一个 getter 来复制整个数组,如果你的场景允许,最好有一个 getArrayElement(int position) 你只是 return 一个数组元素而不是整个数组 - 复制一个数组是昂贵的。
您可以制作一个 getter returns 不可变值的可变副本。
如果您使用数组复制,副本中的值仍然是最终值。
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);
}
}
...一些伪代码 -> 用于将可迭代对象复制为可变形式。
public collection<int>(final collection<final int> finalCollection )
collection nonFinalCollection = new collention();
for(k : finalCollention){collection.add((int) k)}
return(collection)
假设我有一个数组
public static final String[] fooArray ={ Foo.a, Foo.b, Foo.c };
其中 Foo.a b 和 c 是静态最终字符串。
我还能做类似 fooArray[0] = "taco";
的事情并以 { taco, Foo.b, Foo.c }
作为 fooArray 的内容结束吗?
如果是这样,是否可以将数组设为私有,并使用 getter 使用 Arrays.copyOf
制作数组副本来解决此问题?
是的。
A final
数组意味着您不能重新分配数组。
所以你不能这样做:fooArray = new String[]{...};
。
但是您可以更改数组中的内容。这是这样说的效果: "You can't change the box, but you can change the apples inside the box to be oranges." 框保持不变,并且是最终的,但是您实际上已经更改了内容。
也就是说,如果封装 class,那么您可以在需要时克隆数组。
许多 classes 目前都采用这种方法,例如 String#toCharArray
and Enum#values
,其中更改数组的内容包括最终对象的完整性。
final
适用于数组引用,而不是其条目。仍然可以将不同的字符串写入其条目。
If so, would making the array private, and having a getter that makes a copy of the array using Arrays.copyOf solve this issue?
是的,防御性副本是处理此问题的一种相当标准的方法。
或者,鉴于您所概述的内容,您根本不需要数组,只需 getter 如下所示:
public String[] getFooArray() {
return new String[] { Foo.a, Foo.b, Foo.c };
}
或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...
final
-修饰符只会阻止更改fooArray
-引用,而不是数组本身的内容。将其设为私有并让 getter 返回副本会隐藏原始数组,对返回数组所做的任何更改只会影响副本。但是,仍然可以通过反射修改原始数组,但如果您的目的只是为了防止意外修改原始数组,那是可行的。
关于最后一口井的其他人已经回答了。只是对另一部分的建议 - 而不是实现一个 getter 来复制整个数组,如果你的场景允许,最好有一个 getArrayElement(int position) 你只是 return 一个数组元素而不是整个数组 - 复制一个数组是昂贵的。
您可以制作一个 getter returns 不可变值的可变副本。 如果您使用数组复制,副本中的值仍然是最终值。
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);
}
}
...一些伪代码 -> 用于将可迭代对象复制为可变形式。
public collection<int>(final collection<final int> finalCollection )
collection nonFinalCollection = new collention();
for(k : finalCollention){collection.add((int) k)}
return(collection)