1

Javaの「最終」の概念を理解するのに少し苦労しています。

次のクラスがあります。

 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 にコピーして、1 つを編集し、もう 1 つを保持する 2 つの配列を作成するにはどうすればよいでしょうか?

ありがとうございます。

4

5 に答える 5

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

コードの最後の部分はここから取られました: Java の不変配列

于 2012-10-12T04:13:34.113 に答える
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); 
}

これで、アレイが外部から変更されることを心配する必要はありません。

于 2012-10-12T04:30:34.597 に答える
0

MYARRAY_ORIGINAL実際には読み取り専用変数です。配列参照に新しい値を割り当てることも、配列の長さを変更することもできません。最終的な変数の初期化は、コンストラクターが呼び出されるまで延期できます。最終変数の参照を変更しようとすると、コンパイラはエラー メッセージをスローします。しかし、可能なことは、MYARRAY_ORIGINALおよび の要素を編集できることです。myArrayつまり、最終変数に割り当てられたオブジェクトの状態を変更できます。例えば

クラス A { 最終的な 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 の詳細を理解するには、final 変数のJava 言語仕様をご覧ください。

于 2012-10-12T04:22:05.753 に答える
0

の場合Objectsfinal参照は変更できませんが、オブジェクトの状態は変更できます。

これが、値を変更できる理由です。final MYARRAY_ORIGINAL

于 2012-10-12T04:12:17.220 に答える
0

Final は、それ自体が「読み取り専用」であることを意味するのではなく、それが定義されているスレッド以外のスレッドに対する「安全なパブリケーション」を意味します。環境。

第二に、何かを「最終」として定義すると、たとえば次のようになります。

 private final int[][] MYARRAY_ORIGINAL;

参照は「最終」ですが、オブジェクト自体ではありません。それを理解するためのはるかに良い方法は次のとおりです。

public static final List myList = new ArrayList();

これで、他のスレッドから myList にアクセスできるようになりました。変更 (追加) できます。しかし、私はできません (a) 再度宣言する - myList = new ArrayList(); (b) 別のリストを割り当てます - myList = anotherList;

マルチスレッドのシナリオでは、最終的なコンテキストが最もよく見えます。

ボーナス:あなたの質問に答えるには、「読み取り専用」配列を作成することはできません。それを自分で管理する必要があります(最終的には、オブジェクトではなく参照するために「読み取り専用」のみを維持します)

于 2012-10-12T04:25:08.530 に答える