в java какая разница между добавлением каждого элемента в список и просто назначением списка другому - PullRequest
0 голосов
/ 24 июня 2019

может кто-нибудь подсказать, пожалуйста, разница между добавлением каждого элемента в список и просто назначением списка другому

// этот конструктор не проходит некоторые тесты

public Assembler(List<Fragment> fragments) {
    this.fragments = fragments;
}

// тогда как этот конструктор передает их все

public Assembler(List<Fragment> fragments) {
    for(int i = 0; i<fragments.size(); i++){
           this.fragments.add(fragments.get(i));
       }

}

Ответы [ 2 ]

1 голос
/ 24 июня 2019

Ваш первый пример:

public Assembler(List<Fragment> fragments) {
    this.fragments = fragments;
}

В первом примере вы перезаписываете список. Любые элементы, которые использовали , чтобы быть в this.fragments, теперь больше не находятся в this.fragments - скорее, this.fragments теперь указывает на совершенно новый список.

То, имеет ли значение , зависит от того, как this.fragments было объявлено изначально. Вполне возможно, что он был объявлен таким образом, что он уже содержал некоторые переменные:

private List<Fragment> fragments = new ArrayList<Fragment>(Arrays.asList(fragment1, fragment2, fragment3));

В этом случае все они будут перезаписаны. Но это необычное поведение для переменной экземпляра.

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

Assembler a = new Assembler(fragments);
assertFalse(fragments == a.fragments);

в этом случае будет явно проверяться, что вы не просто скопировали список, оценивая, вызывается ли одна и та же ссылка.

Точно так же, если вы выполнили задание, это может привести к непреднамеренному поведению, такому как добавление элемента в fragments и отображение его в a.fragments - что также, вероятно, нежелательно.


В последнем примере вместо этого вы добавляете в список:

public Assembler(List<Fragment> fragments) {
    for(int i = 0; i<fragments.size(); i++){
           this.fragments.add(fragments.get(i));
       }

}

Это сохраняет ссылки на каждый отдельный элемент, но без переназначения this.fragments - так что даже после этого fragments и this.fragments ссылаются на разные объекты, и, таким образом, изменение одного не изменит другого.

Однако есть более краткий способ сделать это, чем циклический цикл for:

public Assembler(List<Fragment> fragments) {
    this.fragments.addAll(fragments);
}
1 голос
/ 24 июня 2019

Я создал очень простой метод, который показывает разницу.В первом случае оба List ссылаются на один и тот же объект, поэтому изменение одного из них приведет к изменению обоих.Во второй версии они будут отдельными, поэтому изменение одного не изменит другого.

     List<String> frag1 = new ArrayList<>();
     List<String> frag2 = new ArrayList<>();
     List<String> frag3 = new ArrayList<>();

     frag1.add("I was added to frag1");
     frag1.add("I also was added to frag1");


     frag2 = frag1;

     for (String s : frag1)
     {
     frag3.add(s);
     }

     frag2.add("I was added to frag2");
     frag3.add("I was added to frag3");

     System.out.println("Frag1: " + frag1.toString());
     System.out.println("Frag2: " + frag2.toString());
     System.out.println("Frag3: " + frag3.toString());

Это приведет к выводу:

Frag1: [I was added to frag1, I also was added to frag1, I was added to frag2]
Frag2: [I was added to frag1, I also was added to frag1, I was added to frag2]
Frag3: [I was added to frag1, I also was added to frag1, I was added to frag3]

Как вы можете видеть, исходный List былизменился, когда Frag2 добавил значение к нему, и Frag1 и Frag2 оба равны.Однако добавление String к Frag3, использующему второй способ его построения, не повлияло на исходное значение Frag1 и теперь отличалось от Frag2 и Frag1.

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