Цель конструктора копирования, когда существует метод клонирования?

1

Из этого SO-вопроса, ответов и комментариев я знаю, что результат

ArrayList<Object> listClone = new ArrayList<Object>(list);

делает дополнительный шаг за кулисами по сравнению с

@SuppressWarnings("unchecked")
ArrayList<Object> listClone = (ArrayList<Object>)list.clone();

но результаты те же. Итак, почему существует даже Copy Constructor когда у нас есть Clone Method?

ПРИМЕЧАНИЕ. Этот вопрос в основном направлен на ArrayList, так как я знаю, что у него есть как Copy Constructor и Clone Method. Если есть какие-либо объекты Java, которые имеют любой из них, но не оба, то я не знал об этом. Тем не менее, мой вопрос направлен на случай ArrayList.

Итак, в чем его цель? В каком случае вы предпочитаете использовать ArrayList Copy Constructor вместо своего Clone Method?

PS: Если у кого-то есть точный код как Copy Constructor и Clone Method для Java#ArrayList для сравнения, это было бы здорово.

  • 3
    я был в ужасе от того, что теги ON видели Java и указатели вместе .. (O_o)
  • 0
    @nobalG Вы очень напуганы, когда видите NPE?
Показать ещё 5 комментариев
Теги:
arraylist
reference
clone
copy-constructor

3 ответа

1
Лучший ответ

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

Вот некоторые плюсы и минусы:

  • Считается, что метод clone() создает проблемы. Во-первых, по умолчанию неясно, подразумевается ли глубокая или мелкая копия. Если вы super.clone() вверх по иерархии, вы можете получить мелкую копию изменчивого объекта, что не было вашим намерением.
  • Некоторые люди используют clone() только для массивов, поскольку там это быстрее.
  • Cloneable неясно. Если что-то Cloneable, все равно может быть очень неясно, с чем вы действительно можете справиться, поскольку у него нет открытого метода clone() и у него нет Object.
  • У конструктора копирования есть преимущество обработки дженериков (как показано на примере Stephen C).

Вот несколько интересных источников для чтения:


Затем вы запросили исходный код конструктора копирования ArrayList и клонирования:

ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();
    size = elementData.length;
    // c.toArray might (incorrectly) not return Object[] (see 6260652)
    if (elementData.getClass() != Object[].class)
        elementData = Arrays.copyOf(elementData, size, Object[].class);
 }


public Object clone() {
    try {
        @SuppressWarnings("unchecked")
         ArrayList<E> v = (ArrayList<E>) super.clone();
         v.elementData = Arrays.copyOf(elementData, size);
         v.modCount = 0;
         return v;
     } catch (CloneNotSupportedException e) {
         // this shouldn't happen, since we are Cloneable
         throw new InternalError();
     }
 }

Получил это от CodeGrep.

3

Итак, в чем его цель?

Посмотрите на подпись конструктора копирования:

   ArrayList(Collection<? extends E> c)

Он создает список из любой коллекции; например LinkedList, любой Set и т.д.

Напротив, вы можете только clone() ArrayList из другого ArrayList.

Теперь есть, несомненно, "проблемы" с clone() в целом. Однако для (по крайней мере) стандартных классов несовпадающих классов клонирование работает так же, как и конструктор копирования... по модулю, что он выполняет эту работу; см. выше. Для этих классов метод clone() определен для возврата неглубокой копии; см. соответствующий класс javadocs.


Если у кого-то есть точный код как Copy Constructor, так и метода Clone для Java # ArrayList для сравнения, это было бы здорово.

Google - ваш друг. Google для источника "java.util.ArrayList" source.

(Я предпочитаю сайт Grepcode. Он имеет несколько версий кода и хороший пользовательский интерфейс для навигации по коду, иерархии пакетов, иерархии классов и даже отношениям определения/использования.)

  • 1
    Обратите внимание, конечно, что источник не должен быть каноническим. Любой может реализовать стандартные библиотеки, если они делают правильные вещи. Это означает, что не обязательно существует «точный код как конструктора копирования, так и метода клонирования».
  • 0
    @JoshuaTaylor - Хороший вопрос. Действительно, GrepCode имеет несколько разных версий java.util.ArrayList начиная от Java 6 до Java 8.
1

Есть небольшая разница, о которой я знаю. Конструктор копирования принимает коллекцию, а не только Arraylist. Это скорее "заполнить все эти материалы в новый ArrayList" -constructor, чем конструктор копирования. Также порядок элементов определяется итератором данного набора.

С другой стороны, метод.clone() создает новый ArrayList из заданного ArrayList.

Одна ситуация, когда эти два работают по-разному:

List a=new ArrayList();
List l=new LinkedList();

List a2 = new ArrayList(a); //returns ArrayList
List a3 = new ArrayList(l); //returns ArrayList
List a4 = a.clone();        //returns ArrayList
List a5 = l.clone();        //returns LinkedList
  • 0
    +1 за пример, в котором их можно использовать по-разному.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню