10

Javaの配列で要素の可視性がどのように機能するかを正確に理解しようとしています。

クラスを考えると:

class IntList {

    private final int[] array;

    public IntList(int[] array) {
        this.array = array;
    }

    public int[] readElements() {
        return Arrays.copyof(this.array, this.array.length);
    }

}    

インスタンスを作成するための次のメソッド本体:

int[] array = new int[length];
fillArrayWithRandomData(array); // puts data into the array from arbitrary source
return new IntList(array);

の要素がIntList、返された への参照を取得する他のスレッドによって表示されることが保証されているかどうか疑問に思っていIntListますか?

配列への参照は最終的なものであるため、表示されると確信していますが、配列内の要素も表示されるという保証を見つけることができないようです。

注:IntListクラスには配列の変更を許可するメソッドがなく、配列参照は他のオブジェクトに発行されません。構築後の可視性についてのみ疑問に思っています。

編集:申し訳ありませんが、私のクラスはString実際の実装では呼び出されません。IntList混乱が多すぎるように見えるので、クラス名を に変更しました。

編集: ここでの最終的な答えは、はい、要素は表示されます。
@MikeClark は JLS の回答を見つけました: JLS § 17.5 「最終フィールドの使用モデルは単純なものです。そのオブジェクトのコンストラクターでオブジェクトの最終フィールドを設定します。別の場所で構築されているオブジェクトへの参照を記述しないでください。スレッドはオブジェクトのコンストラクタが終了する前にそれを見ることができます. これに従えば, オブジェクトが別のスレッドによって見られるとき, そのスレッドは常にそのオブジェクトの最終フィールドの正しく構築されたバージョンを見るでしょう. また, 任意のオブジェクトのバージョンや少なくとも最終フィールドと同じくらい最新の最終フィールドによって参照される配列。」

再度、感謝します!

4

3 に答える 3

-2

あなたの質問には、多くの異なる概念が混同されているようです。

  • 可視性とfinal互いに何の関係もありません
  • 可視性とスレッドは互いに何の関係もありません
  • 変数は、privateそれが final であるかどうかに関係なく、クラス外の他のコードからは見えません。
  • final配列の要素を変更することはできます。であるのは、配列自体への参照のみですfinal

次のようにオブジェクトを構築するIntListとき(ちなみに、名前を変更してくれてありがとう):

public IntList(int[] array) {
    this.array = array;
}

内部this.arrayフィールドは、コンストラクターに渡されたものと同じ配列オブジェクトを参照します。String配列は、クラスの外部から変更できます。

int[] array = {1, 2, 3};
IntList list = new IntList(array);
System.out.println(Arrays.toString(list.readElements()); // prints [1, 2, 3]
array[1] = 0;
System.out.println(Arrays.toString(list.readElements()); // prints [1, 0, 3]

コンストラクターで配列のコピーを作成することにより、クラスをこれから隔離できます。

public IntList(int[] array) {
    this.array = Arrays.copyOf(array, array.length);
}
于 2012-11-20T19:51:08.503 に答える