我在理解Java中“final”的概念时遇到了一些麻烦。
我有一节课:
public class MyClass
{
private int[][] myArray; // intended to be changed
private final int[][] MYARRAY_ORIGINAL; // intended to be unchangable
public MyClass(int[][] array)
{
myArray = array;
MYARRAY_ORIGINAL = array;
}
}
我理解“最终”会使MYARRAY_ORIGINAL只读。但我尝试编辑myArray,它也编辑了MYARRAY_ORIGINAL。我的问题是,在这种情况下,“最终”究竟做了什么?为了获得额外的功劳,我如何将通过构造函数传递的数组复制到MYARRAY_ORIGINAL中,以便我可以拥有2个数组,一个用于编辑,另一个将保留?
先谢谢。
答案 0 :(得分:3)
您的final MYARRAY_ORIGINAL
确实是只读的:您不能在类构造函数或属性声明的其他方面为MYARRAY_ORIGINAL
引用分配新值:
public void someMethod() {
//it won't compile
MYARRAY_ORIGINAL = new int[X][];
}
数组中的值不是 final。这些值可以随时在代码中更改。
public void anotherMethod() {
MYARRAY_ORIGINAL[0][0] = 25;
//later in the code...
MYARRAY_ORIGINAL[0][0] = 30; //it works!
}
如果你确实需要一个最终元素列表,换句话说,一个无法修改其元素的List,你可以使用Collections.unmodifiableList
:
List<Integer> items = Collections.unmodifiableList(Arrays.asList(0,1,2,3));
最后一段代码来自这里:Immutable array in Java
答案 1 :(得分:0)
如果Objects
,则final
无法更改引用,但可以更改对象状态。
这就是为什么您可以更改final MYARRAY_ORIGINAL
答案 2 :(得分:0)
MYARRAY_ORIGINAL
确实是只读变量。您的数组引用不能分配新值,也不能更改它们的数组长度。可以推迟最终变量初始化,直到调用构造函数。如果尝试修改最终变量的引用,编译器将抛出错误消息。但是可能的是,可以编辑MYARRAY_ORIGINAL
和myArray
的元素,即可以改变分配给最终变量的对象的状态。例如
A类{ final int [] array;
public A() {
array = new int[10] // deferred initialization of a final variable
array[0] = 10;
}
public void method() {
array[0] = 3; // it is allowed
array = new int[20] // not allowed and compiler will throw an error
}
}
要了解有关最终结果的更多信息,请查看最终变量Java Language Specification。
答案 3 :(得分:0)
最终并不意味着'只读'本身,但更多的是“安全发布”用于其他线程,而不是它所定义的线程。“最终”的另一个目标是确保最新的对象可用于多线程环境。
其次,如果您将某些内容定义为“final”,例如:
private final int[][] MYARRAY_ORIGINAL;
引用是“final”,但不是对象本身。理解它的更好方法是:
public static final List myList = new ArrayList();
现在我可以从任何其他线程访问myList - 我可以修改它(添加到它);但是我不能 (a)再次声明它 - myList = new ArrayList(); (b)为其分配另一个列表 - myList = anotherList;
在多线程场景中,我将看到最终的上下文。
奖励:要回答你的问题,你不能制作一个'只读'数组,你必须自己管理(最后,只保持'只读'来引用不是对象)
答案 4 :(得分:0)
您可以使用方法System.arraycopy
制作数组的副本,如下所示 -
int[][] source = {{1,2},{3,4}};
int[][] copy = new int[source.length][];
System.arraycopy(source, 0, copy, 0, source.length);
此外,您的代码与您尝试执行的操作有关。如果你看一下构造函数
public MyClass(int[][] array) { //something else passes the array
myArray = array;
MYARRAY_ORIGINAL = array; // you are just keeping a reference to it can be modified from outside
}
如果你真的希望没有人修改该数组MYARRAY_ORIGINAL
中的值,你应该复制来自外部的源数组。
public MyClass(int[][] array) {
myArray = array; //make a copy here also if you don't want to edit the argument array
MYARRAY_ORIGINAL = new int[array.length][];
System.arraycopy(array, 0, MYARRAY_ORIGINAL, 0, array.length);
}
现在你不必担心从外面修改数组。