&引用;“最后的”;在java中复制二维数组

&引用;“最后的”;在java中复制二维数组,java,clone,final,multidimensional-array,Java,Clone,Final,Multidimensional Array,我在理解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

我在理解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;
     }

 }
我的理解是“final”将使我的数组成为只读的。但我试过编辑myArray,它也会编辑myArray_ORIGINAL。我的问题是,在这种情况下,“最终”到底是做什么的?为了获得额外的积分,我如何将通过构造函数传递的数组复制到MYARRAY_ORIGINAL中,这样我就可以有两个数组,一个要编辑,另一个要保留


感谢高级。

对于
对象
最终
使引用无法更改,但对象状态可以更改


这就是为什么您能够更改
final MYARRAY\u ORIGINAL
的值的原因。您的
final MYARRAY\u ORIGINAL
实际上是只读的:除了类构造函数或属性声明之外,您不能将新值分配给
MYARRAY\u ORIGINAL
引用:

public void someMethod() {
    //it won't compile
    MYARRAY_ORIGINAL = new int[X][];
}
数组中的值不是最终值。这些值可以在代码中随时更改

public void anotherMethod() {
    MYARRAY_ORIGINAL[0][0] = 25;
    //later in the code...
    MYARRAY_ORIGINAL[0][0] = 30; //it works!
}
如果您确实需要一个最终元素列表,换句话说,一个元素无法修改的列表,您可以使用:

List items=Collections.unmodifiableList(Arrays.asList(0,1,2,3));

最后一段代码取自此处:

MYARRAY\u ORIGINAL
确实是只读变量。不能为数组引用指定新值,也不能更改其数组长度。最终的变量初始化可以推迟到调用构造函数。如果试图修改最终变量的引用,编译器将抛出错误消息。但可能的是,可以编辑
MYARRAY\u ORIGINAL
MYARRAY
的元素,即可以更改分配给最终变量的对象的状态。比如说

甲级{ 最终int[]数组

 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

 }
}

要了解有关final的更多信息,请查看on final变量。

final本身并不意味着“只读”,但对于定义它的线程以外的其他线程来说更是“安全发布”。final的另一个目的是确保在多线程环境中提供最新的对象

其次,如果您将某事物定义为“最终”,例如:

 private final int[][] MYARRAY_ORIGINAL;
参考是“最终的”,但不是对象本身。更好的理解方法是:

public static final List myList = new ArrayList();
现在我可以从任何其他线程访问myList—我可以修改它(添加到它);但我不能 (a) 再次声明-myList=newarraylist(); (b) 给它分配另一个列表-myList=anotherList

在多线程场景中,我最了解final的上下文

奖励:要回答您的问题,您不能创建“只读”数组,您必须自己管理该数组(最终,只维护“只读”以引用非对象)

您可以使用该方法创建数组的副本,如下所示-

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\u 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); 
}

现在,您不必担心数组被从外部修改。

感谢您的回答Luiggi。另一个快速跟进问题是,您认为我应该怎么做才能实现两个数组,一个用于编辑,一个用于原始?有没有比循环二维数组并复制所有值更方便的方法?@DavisSmith使用上一次编辑中显示的不可修改列表,或为不可修改数组创建类包装器,并确保此类永远不会修改数组元素。如果您想要简单的方法,请使用第一个选项,如果您无法使用
列表
界面,请使用第二个选项。
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); 
}