ArrayList ссылается на поведение - PullRequest
0 голосов
/ 12 февраля 2012

Я полностью сбит с толку поведением ArrayList. Написал действительно длинный пост, потом понял, что никто не собирается анализировать огромный код, поэтому просто суть проблемы. Числа приведены для удобства, но в моем приложении эти 0 и 24 являются динамическими значениями.

ArrayList<VoipBlock> sortedBlocks = new ArrayList<VoipBlock>();

VoipBlock vb3 =new VoipBlock();

vb3=sortedBlocks.get(0);

vb3.setPacketNumber(24); 

По сути, моя последняя цель: изменить и добавить обратно в arrayList как новое значение. Однако, когда я делаю это, парень в позиции 0 в ArrayList -> unsortedBlocks.get (0); копирует все изменения, сделанные в vb3 , что, конечно, не то, что я хочу. Я хочу, чтобы vb3 получал те же значения, что и VoipBlock внутри ArrayList, но я хочу, чтобы он был отключен.

Это еще один случай передачи по ссылке. Я ненавижу технические объяснения - Java передает все по значению, НО в некоторых случаях передает ссылки по значениям - это то же самое, что сказать, что масло не жирное. Пожалуйста, помогите.

Это напоминает мне о том, что я начал изучать JavaScript - я ненавидел этот язык - пока не посмотрел подходящие материалы на lynda.com - JavaScript Good Practices? - Диаграммы убили меня. Это ленивое описание, которое отвлекает нас - молодежь от блестящей технологии, а не самой технологии.

Пожалуйста, не позволяйте этому беспокоить мой стресс и ни в коем случае не обижайтесь на меня, это просто общие жалобы, может быть, кто-то посмотрит на это и сделает жизнь лучше: -)

Спасибо за ваше время, Отчаянно ожидая помощи: -)

Ответы [ 4 ]

1 голос
/ 12 февраля 2012

Если я правильно понимаю, вы немного не уверены в том, как работают ссылки и значения.Я думаю, что практическое правило заключается в том, что примитивные типы, такие как int, char, boolean и, возможно, String, копируются, но объекты просто передают свою ссылку.

Строка vb3=sortedBlocks.get(0); полностью заменяет любой vb3, который использовался в первомвещь в ArrayList.И да, это не будет копия, это будет ссылка на тот же объект в памяти.То, что вы делаете, повлияет на них обоих.Вам необходимо либо вручную скопировать всю необходимую информацию, либо использовать функцию clone() или copy().

Так, например, в вашем коде строка VoipBlock vb3 =new VoipBlock(); немного избыточна, потому что выперезаписываем новый экземпляр сразу.

1 голос
/ 12 февраля 2012

Для достижения своей цели вы можете использовать метод клонирования. Вы должны переопределить этот метод в классе VoipBlock

Допустим, VoipBlock выглядит следующим образом

public class VoipBlock {

     private int packetNumber;
     private String type;

     public int getPacketNumber() {
      return packetNumber;
     }

     public String getType() {
      return type;
     }

     public void setPacketNumber(int value) {
       packetNumber = value;
     } 

     public void setType(String value) {
       type = value
     }

     public VoipBlock clone() {
        VoipBlock clone = VoipBlock();
        clone.setType(this.getType());
        clone.setPacketNumber(this.getPacketNumber());
        return clone;
     }

}

Итак, используя тот же код, вы можете сделать это следующим образом

ArrayList<VoipBlock> sortedBlocks = new ArrayList<VoipBlock>();

VoipBlock vb3 =new VoipBlock();

sortedBlocks.add(vb3);

vb3=sortedBlocks.get(0).clone();

vb3.setPacketNumber(24);

Обратите внимание, что при вызове метода клона в вышеуказанном сегменте кода vb3 назначается с новым экземпляром VoipBlock. И уже вставленный VoipBlock в массив остается без изменений.

если вы ищете типовые экземпляры экземпляров VoipBlock, которые вы позже захотели использовать при создании подобных экземпляров, подобных им. проверить неизменяемость / изменчивость аспекта кода. чек "Эффективная Ява" Джошуа Блаша

1 голос
/ 12 февраля 2012

Следующая ссылка всегда будет копировать ссылку b на a:

AnyClass a = ...;
AnyClass b = ...;
a = b;

Вероятно, вам нужно клонировать объект:

a = b.clone();
0 голосов
/ 12 февраля 2012

Здесь вам действительно нужно либо использовать конструктор копирования, либо объявить VoipBlock как Clonable, чтобы вы могли использовать метод clone ().

То, что вы интерпретируете как передачу по ссылке, на самом деле не является передачей по ссылке. Объекты Java на самом деле являются указателями. Из-за этого вы передаете значение указателя. Итак, когда вы делаете:

vb3=sortedBlocks.get(0);

вы действительно назначаете vb3 для указания на те же места в памяти, что и sortedBlocks.get (0). Поэтому, когда вы манипулируете свойствами vb3 через их установщики, результат виден в обоих случаях.

Если вам нужны два отдельных указателя, вам нужно использовать ключевое слово new или использовать метод clone (), который делает это скрытно.

Пример, подтверждающий это:

public class Person {
  private String name;

  public Person(String name) {
    this.name = name;
  }

  public String getName() {
    return this.name;
  }

  public void setName(String name) {
     this.name = name;
  }
}

public class Main {

  public void doSomething(Person p) {
    p = new Person("Bob");
    System.out.println(p.getName());
  }

  public static void main(String[] args) {
    Person p = new Person("Billy");
    System.out.println(p.getName());
    doSomething(p);
    System.out.println(p.getName());
  }
}

Поскольку Java передается по значению, вывод будет: Билли, Боб, Билли. Если бы Java передавалась по ссылке, это был бы Билли, Боб, Боб. Если бы я не делал новый объект Person в методе doSomething () и вместо этого использовал метод setName (), я бы тоже получил Билли, Боба, Боба, но это из-за того, что я теперь изменяю тот же указатель, но не то, что я передал по ссылке в качестве примера выше, доказывает, что это не так.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...