2012-10-12 49 views
1

我在Java中理解「final」的概念時有點麻煩。java中的「最終」和複製2D數組

我有如下的類:

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個數組,一個可以編輯,另一個可以保留?

謝謝先進。

回答

3

值的原因,你的final MYARRAY_ORIGINAL只有確實寫着:你不能將新值分配給對方比類的構造MYARRAY_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! 
} 

如果你確實需要的最終元素的列表,換句話說,一個列表,其元素不能被修改,你可以使用Collections.unmodifiableList

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

代碼的最後一塊被送往從這裏開始:Immutable array in Java

+0

謝謝你的迴應Luiggi。另一個快速跟進問題,你認爲我應該怎麼做才能實現兩個數組,一個是編輯和一個原創?有沒有比循環2D數組和複製所有值更方便的方法? –

+0

@DavisSmith使用最後一次編輯中顯示的不可修改列表,或者爲不可修改的數組創建類包裝,並確保此類永遠不會修改數組元素。如果您想要簡單的方法,請使用第一個選項,如果您不能使用'List'接口,請使用第二個選項。 –

0

如果是Objects,final使引用無法更改,但可以更改對象狀態。

這就是爲什麼你能夠改變的final MYARRAY_ORIGINAL

0

MYARRAY_ORIGINAL確實是只讀變量。您的數組引用不能被分配一個新的值,也不能改變它們的長度。最後的變量初始化可以推遲到構造函數被調用。如果試圖修改最終變量的引用,編譯器會拋出一條錯誤消息。但可能的是,可以編輯MYARRAY_ORIGINALmyArray的元素,即可以更改分配給最終變量的對象的狀態。例如,

A類{final} []數組;

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的內容,請查看Java Language Specification上的最終變量。

0

最終並不意味着'只讀'本身,而更多的是「安全發佈」的其他線程,而不是它定義的那個線程。'final'的另一個目的是確保最新的對象可用多線程環境

其次,如果你定義的東西作爲「最終」,例如:

private final int[][] MYARRAY_ORIGINAL; 

基準是「最終的」,而不是對象本身。一個更好的方法去理解它會是這樣:

public static final List myList = new ArrayList(); 

現在我可以從任何其他線程訪問myList中 - 我可以修改它(添加到它)。但我不能 (a)再次聲明它 - myList = new ArrayList(); (b)將它分配給另一個列表 - myList = anotherList;

最終的上下文會在多線程場景中看到最好。

獎勵:回答你的問題,你不能讓一個「只讀」數組,你必須來管理自己(作爲最終,僅保留「只讀」引用不反對)

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

現在你不應該擔心數組被外界修改了。