Переменная типа ArrayList, присвоенная другому, передается как ссылка в Android Java

#java #android #arraylist

#java #Android #arraylist

Вопрос:

Я разрабатываю проект Android. Прежде всего, я не разработчик Java. Теперь я хочу кое-что узнать о программировании на Java, особенно о ArrayList.

Вот мой код:

         ArrayList<Bitmap> previewBitmaps = new ArrayList<Bitmap>();
        //initialize values - total 3 elements
        previewBitmaps.remove(2);
        ArrayList<Bitmap> temp = new ArrayList<Bitmap>();
        temp = previewBitmaps;
        previewBitmaps.removeAll(previewBitmaps);
        //here temp size become zero because previewBitmaps cleared
  

Как вы можете видеть в приведенном выше коде, я удаляю элемент из previewBitmaps, затем я назначил остальные 2 элемента для temp. Таким образом, размер temp будет равен 2. Затем я очищаю previewBitmaps. Таким образом, размер previewBitmaps становится равным 0. Но проблема в том, что размер temp также становится равным 0. Почему?

На самом деле размер temp должен быть 2. Верно? Что мне не ясно, так это то, назначена ли она в качестве ссылочной переменной в C? Почему? Как я могу очистить эту ссылку?

Ответ №1:

Здесь temp = previewBitmaps; вы присваиваете адрес памяти вашего previewBitmaps ArrayList temp . Это означает, что они оба указывают на один и тот же адрес памяти. Каждое действие, которое вы выполняете с одним, будет применяться к обоим, потому что они указывают на один и тот же объект в памяти.

Если вы хотите создать новую копию ArrayList, вы можете использовать это: temp = new ArrayList(previewBitmaps);

Комментарии:

1. О, спасибо. Но в C # temp = previewBitmaps; не будет указывать на тот же адрес памяти. Верно?

2. Я не знаю о C #, но я думаю, что это, скорее всего, будет указывать на тот же адрес памяти.

3. Я знаю о c #, и это то же самое с java там 😉

4. Да, я так и думал.

Ответ №2:

Потому что, когда вы назначаете один непримитивный объект другому, на самом деле java заставляет обе эти переменные указывать на одно место в памяти. При изменении данных в памяти будут затронуты обе эти переменные .

Только примитивный тип не действует так, например, для переменной int такого не произойдет, но для всех непримитивных типов это так 😉

Примитивными типами являются int, float, char, …

Ответ №3:

Ваша проблема в основном: не пытайтесь изучать программирование на Java и Android одновременно.

Пример:

 ArrayList<Bitmap> previewBitmaps = new ArrayList<Bitmap>();
  

создает новую пустую карту. Так же:

 ArrayList<Bitmap> temp = new ArrayList<Bitmap>();
  

но ваша следующая строка

 temp = previewBitmaps;
  

отбрасывает список, который вы создали на предыдущем шаге. Исчезла. Какой смысл создавать новый список, чтобы потом его выбросить ?!

Происходит то, что две переменные previewBitmaps и temp указывают на одну и ту же ссылку. Таким образом, вы не манипулируете двумя разными списками, а только одним списком впоследствии.

Если ваша идея заключалась в создании «временной» копии первого списка; вы могли бы делать

 List<Bitmap> temp = new ArrayList<>(previewBitmps);
  

вместо этого (приведенное выше создает новый список, содержащий все элементы другого списка).

И, пожалуйста, обратите внимание: в качестве типов вы должны предпочесть использовать более абстрактные интерфейсы, такие как List . Вы используете только конкретный тип (например, ArrayList при создании объектов); после этого вы должны обращаться к объектам только с помощью интерфейса списка.

Таким образом: сначала сосредоточьтесь на таких основах Java! В противном случае ваш опыт работы с Android будет очень коротким и разочаровывающим. Поскольку вы будете переходить от одной проблемы к следующей. Научитесь сканировать, прежде чем пытаться запустить.

Ответ №4:

Для вас, чтобы установить значения previewBitmaps в temp. Возможно, вы захотите использовать temp.addAll(previewBitmaps);

Ответ №5:

previewBitmaps — это ссылочные переменные, которые указывают на объект. Теперь, когда вы удаляете элемент в позиции 2, объект (список) приобретает размер 2. Теперь, когда вы пишете ArrayList<Bitmap> temp = new ArrayList<Bitmap>() , он создает новый объект в кучной памяти, а ссылочная переменная temp указывает на этот новый объект. Затем вы вызываете temp = previewBitmaps . Теперь temp указывает на тот же объект, на который указывает previewBitmaps. Поэтому, когда вы вызываете

 previewBitmaps.removeAll(previewBitmaps); 
  

она удаляет все элементы из объекта, на который указывают обе ссылочные переменные, т.е. previewBitmaps и temp .

Ответ №6:

Это происходит, когда вы присваиваете две ссылки одному и тому же объекту. Вам нужно создать глубокий клон текущего ArrayList вместо мелкого.

for(Bitmap b: previewBitmaps){
temp.add(b.clone())
}

Выполнение temp = previewBitmaps.clone() не поможет, поскольку оно создаст новый ArrayList , но оба списка будут указывать на одни и те же объекты внутри. Это известно как мелкий клон.