1

finalというインスタンス変数を持つ次のコードを試してみましたdata。これは、引数を使用してコンストラクターでインスタンス化されますint[]。int[] 配列の要素が変更された場合、変更はインスタンス変数に反映され、show()'s出力に表示されます。ただし、外部配列を null または新しい配列に設定すると、変更は show() 出力に反映されません。

なぜこれが起こるのですか?外部配列が ext[0]=x によって変更された場合、変更は inst.variable に表示されます。ext 参照が新しいオブジェクトに設定されている場合は発生しません。

public class MutabilityTest {
    public static void main(String[] args) {
    int[] ext =  new int[] {1,2,3,4,5};
        FMutable xmut = new FMutable(ext);
        mut.show();    //shows [1,2,3,4,5]
        System.out.println("changed ext array");
        ext[0] = 99;
        System.out.println("ext:"+Arrays.toString(ext)); //[99,2,3,4,5]
        mut.show();    //shows [99,2,3,4,5]
        System.out.println("set ext array to new");
        ext = new int[]{8,8,8,8} 
        System.out.println("ext:"+Arrays.toString(ext)); //[8,8,8,8]
        mut.show();//expected [8,8,8,8] but got [99,2,3,4,5]
        ext = null;
        System.out.println("ext:"+Arrays.toString(ext)); //null
        mut.show(); //shows same [99,2,3,4,5]
    }
}
class FMutable{
    private final int[] data;
    public FMutable(int[] indata){
    this.data = indata;
    }
    public void show(){
    System.out.println("XMutable:"+Arrays.toString(this.data));
    }
}
4

4 に答える 4

3

dataこれは、final であることや、他の場所のフィールドとは関係ありません。まったく同じ効果をより簡単に確認できます。

int[] x = { 1, 2, 3, 4, 5 };
int[] y = x;

y[0] = 10;
System.out.println(Arrays.toString(x)); // 10, 2, 3, 4, 5
y = new int[] { 3, 3, 3, };
System.out.println(Arrays.toString(x)); // 10, 2, 3, 4, 5

変数、その値、およびオブジェクトを区別することが重要です。変数は一枚の紙のようなものと考えてください。プリミティブ値または家の住所を書き込むことができます。

この線:

int[] y = x;

またはサンプルコードで:

this.data = indata;

一枚の紙に書かれていることを新しい紙にコピーするだけです。これは、「家」(この場合は配列オブジェクト) の住所です。

現在、これら 2 枚の紙はそれ自体が独立しています。一方に書かれている内容を変更しても、他方に書かれている内容は変更されません。ただし、1 枚の紙の住所に従って家に行く場合は、変更を加えて (たとえば、玄関のドアにペンキを塗る)、もう 1枚の紙の住所に従って家に行きます (それらがまだ残っている間に)。同じ)そうです、塗りたてのドアが見えます。これは、配列自体に変更を加えたときに表示されるものです。

于 2013-10-01T07:01:55.097 に答える
1

ext = new int[]{8,8,8,8}変数の新しい配列を作成しますが、オブジェクトextのフィールドには影響しません。datafinal でない場合、同じ効果が発生することに注意してくださいdata

final参照を一度だけ設定できることを意味しますが、オブジェクトは引き続き操作できます。

于 2013-10-01T07:00:11.493 に答える
1

extdataインスタンス配列と同じメモリ位置を指している別の参照です。null に設定すると、参照extのみが設定され、配列には設定されません。extnulldata

于 2013-10-01T06:59:14.390 に答える
1
final int[] data

これは、配列オブジェクトが最終的であることを意味します(一度初期化でき、その後は変更できません)が、index'sそうではありません。

コンストラクターを介して初期化したもの。

public FMutable(int[] indata){
    this.data = indata;
}

ext同じオブジェクトを指す別の参照です。同じオブジェクトに対する変更はfinal data、両方が同じを参照するため、フィールドにも影響しますObject

ただし、参照データは最終的なものであるため、再初期化することはできません。そしてext = new int[]{8,8,8,8}、新しい配列を作成し、ext はそれを指します。

于 2013-10-01T06:59:19.757 に答える