2013-10-01 4 views
1

Я попробовал следующий код, который имеет переменный с final экземпляра под названием data .Это экземпляра в конструкторе с использованием int[] argument.If элемента Int [] изменения массива, изменение отражается в переменной экземпляра и показано в выводе show()'s. Однако, если я устанавливаю внешний массив в нуль или в новый массив, это изменение не отражается в выводе show().конечные переменная экземпляра массива в классе Java и сброс ссылки

Почему это происходит? если внешний массив изменен ext [0] = x, это изменение отображается в inst.variable.It не происходит, если ссылка 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)); 
    } 
} 
+0

in java .. Объект paassed по refrence и типам данных, переданным по значению ... –

ответ

3

Это не имеет никакого отношения к data, являющемуся окончательным, или полем в другом месте. Вы можете увидеть тот же эффект гораздо проще:

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; 

просто копирует то, что написано на одном листе бумаги на новый лист бумаги. Это просто адрес «дома» (объект массива в этом случае).

Теперь эти две части бумаги сами по себе независимы - изменение того, что написано на одном из них, не меняет того, что написано на другом. Однако, если вы идете в дом, следуя адресу на одном листе бумаги, внесите изменения (например, нарисуйте переднюю дверь), а затем перейдите в дом, следуя по адресу на других лист бумаги (в то время как они " все-таки то же самое), тогда да, вы увидите свежесручную дверь. Это то, что вы видите, когда делаете изменения в самом массиве.

+0

Я видел это объяснение ранее. Да, я помню, я видел это в одном из ваших более ранних ответов тоже с тем же примером. Nice one :) –

+2

@RohitJain: Да, я имею в виду написать его в статье или блоге некоторое время, поэтому я могу просто сослаться на него :) –

1

ext просто еще одна ссылка указывает на то же место памяти как массив data экземпляра. Если вы установили ext в null, он установит только ext ссылку на null, а не на массив data.

1
final int[] data 

Это означает, что ваш obejct массив является окончательным (вы можете инициализировать один раз и не может измениться после этого), но index's нет.

Что вы инициализировали с помощью конструктора.

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

ext это еще одна ссылка, которая poitning к тому же объекту. Любое изменение на том же объекте также будет влиять на поле final data, так как оба ссылаются на то же самое Object.

Но, поскольку эталонные данные являются окончательными, вы не можете реанимировать. И ext = new int[]{8,8,8,8} создаст новый массив, и ext укажет на это.

1

ext = new int[]{8,8,8,8} создает новый массив для переменной ext, но не влияет на поле data в вашем объекте. Обратите внимание, что тот же эффект будет иметь место, если data не был окончательным!

final означает, что вы можете установить ссылку один раз, однако объект все еще можно манипулировать.

Смежные вопросы