2013-07-17 2 views
1

Я реализовал конструктор копирования, как описано here. Но все же проблема в том, что когда я обновляю route_copy, то такое же обновление применяется к route. Итак, я не понимаю, что не так в моем коде?Конструктор копирования создает зависимую копию

public class Route implements Comparable<Route> { 
    private List<Site> sites; 

    public Route() 
    { 
     sites = new ArrayList<Site>(); 
    } 

    public Route(List<Site> sites) 
    { 
     this.sites = sites; 
    } 

    /** 
    * Copy constructor 
    */ 
    public Route(Route r) { 
     this(r.sites); 
    } 

    public void deleteSite(Site s) { 
     this.sites.remove(s); 
    } 
} 

public processData(Route route) 
{ 
    Route route_copy = new Route(route); 
    Site s = selectSite(route_copy); 
    route_copy.deleteSite(s); // !!! now 'route' does not contain an element 's' 
} 
+0

Ваш «конструктор копирования» не делает копию списка ввода. Попробуйте что-то вроде –

+0

Java не поддерживает конструкторы копирования в той же степени, что и C++, то есть автоматический вызов. Не было бы более целесообразным переопределять 'clone()'? – DuncanACoulter

+0

@DuncanACoulter: У меня была такая же проблема после переопределения метода клонирования и реализации класса Route as Cloneable. –

ответ

5

В конструкторе копирования, вы просто делаете неполную копию, в то время как вам нужно сделать глубокую копию:

public Route(Route r) { 
    this(r.sites); 
} 

Здесь вы все еще скопировать ссылку из list, который до сих пор указывает на то же самое ArrayList. Вы должны изменить его, чтобы создать копию списка. Возможно, вам также необходимо создать копию элементов внутри ArrayList как так:

public Route(Route r) { 
    List<Site> newSites = new ArrayList<Site>(); 

    for (Site obj: r.sites) { 
     // Add copy of obj to the newSites 
     // So you need yet another copy constructor in 'Site' class. 
    } 

    this.sites = newSites; 
} 

Проверить этот пост - Shallow Copy vs Deep Copy.

+1

Это не скомпилируется. 'this (...)' должен быть первым выражением в конструкторе. – DannyMo

+1

@damo. Упс. Исправлена. Спасибо :) –

+0

ITSPoI по-прежнему будет ссылаться на тот же ITSPoI в списке 2, если вы измените объект в списке, будет отображаться, все еще мелкая копия – nachokk

2

Ваш «конструктор копирования» не делает копию списка ввода. Попробуйте что-нибудь наподобие

public Route(List<Site> sites) 
{ 
    this.sites = new ArrayList<Site>(sites); 
} 

для вашего второго конструктора.

+0

Будет ли это создавать полностью независимую копию? –

+0

Создает копию ArrayList , но не содержит элементы, принадлежащие самому списку (объекты сайта). –

+1

@KlausosKlausos ... что означает, что while 'copyList.remove()' не повлияет на исходный список; 'copyList.get (i) .setSomething (" ")' будет. Таким образом, это зависит от того, как вы собираетесь использовать копию. –

1

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

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

sites = new ArrayList<Site>(oldList); 
2

Ofcourse он будет создавать зависимую копию также называется Малой копии.

Вам необходимо Deep копия.

2

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

Вы можете попробовать использовать конструктор копирования из ArrayList:

общественного ArrayList (Collection с)

Создаёт список , содержащий элементы указанной коллекции, в порядке их являются возвращенный итератором коллекции.

Как так:

 public Route(Route r) { 
    this(new ArrayList<Site>(r.sites)); 
    } 

Заметит, однако, что делать какие-либо изменения в Site объектов в списке может иметь repurcussions на других объектах, хранящихся в другом списке, в зависимости от того, насколько сложна вашей Site объекта ,

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