Вопрос:

Почему один arraylist изменяется, когда его копия модифицируется

java

810 просмотра

6 ответа

1141 Репутация автора

Это, вероятно, очень простой, но все еще смущает меня!

import java.util.ArrayList;

public class Sample {
    ArrayList<Integer> i = new ArrayList<>();
    ArrayList<Integer> j = new ArrayList<>();

    /**
     * @param args
     */
    public static void main(String[] args) {
        new Sample().go();
    }

    private void go() {

        i.add(1);
        i.add(2);
        i.add(3);

        j=i;

        i.remove(0);


        System.out.println(i + "asd" + j);
    }

}

Я попытался напечатать это:

[2, 3]asd[2, 3]

Почему j меняется, когда я меняюсь? Хотя не бывает с примитивами!

Автор: Mercenary Источник Размещён: 24.10.2013 05:48

Ответы (6)


8 плюса

158130 Репутация автора

Решение

Оператор j=i;назначает ссылку jтакой же, как и i. Теперь оба iи jссылаются на один и тот же ArrayListобъект. Удаление 0-го индекса просто видно по обеим ссылкам.

Если вы хотите, чтобы удаление элемента iне влияло на список j, создайте копию списка вместо назначения ссылок:

j = new ArrayList<Integer>(i);

(Это мелкая копия, поэтому списки по-прежнему ссылаются на одни и те же элементы.)

Автор: rgettman Размещён: 24.10.2013 05:49

1 плюс

35916 Репутация автора

использование

j = new ArrayList<>(i);

или же

Collections.copy(j, i);

создать копию.

С j = iвами только сделать jточку i(это называется ссылка). Это относится ко всем назначениям, которые включают объекты (не примитивные типы, такие как intили float)

Автор: micha Размещён: 24.10.2013 05:51

1 плюс

86 Репутация автора

Объект не клонирован, просто добавлена ​​дополнительная ссылка на объект. Поскольку ArrayList не является неизменным, любое изменение объекта отражается в обеих ссылках объекта.

Автор: A myth Размещён: 24.10.2013 05:52

0 плюса

5825 Репутация автора

Объекты и примитивы работают несколько иначе. Думайте об объекте как iо названии этого объекта. Когда вы говорите j=i, что говорите JVM: «забудьте о том, что другой ArrayList, кого я сказал, был вызван j; отныне, когда я имею в jвиду, я имею в виду этот, ArrayListкоторый также может быть вызван i. И действительно, это именно то, что произошло: после этой строки оба переменные ссылаются на один и тот же объект.

Примитивы работают, как вы говорите. Если вы говорите i=5; j=i; i=6, то jвсе равно будет установлен на 5.

Автор: dcsohl Размещён: 24.10.2013 05:53

0 плюса

13126 Репутация автора

Вы создали стадию памяти для j с; j = новый ArrayList <> ();
но потом вы сказали, что пусть j относится к стадии памяти i. Так что после j = i; любые изменения в i или j будут влиять на них обоих. Потому что они ссылаются на одни и те же объекты.

Автор: Devrim Размещён: 24.10.2013 05:54

0 плюса

5924 Репутация автора

Позвольте мне сделать это следующим образом для вас:

ArrayList<Integer> i = new ArrayList<>();
ArrayList<Integer> j = new ArrayList<>();

// checking hash code before j = i;
System.out.println(System.identityHashCode(i));
System.out.println(System.identityHashCode(j));

j = i;

// checking hash code after j = i;
System.out.println(System.identityHashCode(i));
System.out.println(System.identityHashCode(j));

сравнить оба значения, если они одинаковы, что означает, что после j=i; ArrayList jтеперь указывает наArrayList i

В моей машине о / п было:

30269696 //hashCode of i
24052850 //hashCode of j before j = i;

30269696 //hashCode of i and j are same after j = i that means they are pointing to same reference and hence change in one reflects on the other.
30269696
Автор: Vishrant Размещён: 24.10.2013 06:03
Вопросы из категории :
32x32