В Java, что такое мелкая копия?

java.util.Calendar.clone() возвращает "... новый календарь с теми же свойствами" и возвращает "мелкую копию этого Календаря".

Это не выглядит мелкой копией, как было указано здесь на SO. Этот вопрос отмечен language-agnostic, Java, похоже, не соответствует языковому агностическому определению. Когда я просматриваю код, я замечаю, что структура и элементы копируются в этот новый объект, больше, чем только агностическая структура языка.

В Java, что такое мелкая копия?

Как он отличается от глубокой копии Java (если таковой существует)?

Ответ 1

Неглубокая копия просто копирует значения ссылок в классе. Глубокая копия копирует значения. Дано:

class Foo {
  private Bar myBar;
  ...
  public Foo shallowCopy() {
    Foo newFoo = new Foo();
    newFoo.myBar = myBar;
    return newFoo;
  }

  public Foo deepCopy() {
    Foo newFoo = new Foo();
    newFoo.myBar = myBar.clone(); //or new Bar(myBar) or myBar.deepCopy or ...
    return newFoo;
  }
}

Foo myFoo = new Foo();  
Foo sFoo = myFoo.shallowCopy();  
Foo dFoo = myFoo.deepCopy();  

myFoo.myBar == sFoo.myBar => true  
myFoo.myBar.equals(sFoo.myBar) => true  
myFoo.myBar == dFoo.myBar => **false**  
myFoo.myBar.equals(dFoo.myBar) => true  

В этом случае мелкая копия имеет одинаковую ссылку (==), а глубокая копия имеет эквивалентную ссылку (.equals()).

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

С-изм

int a = 10; //init
int& b = a; //shallow - copies REFERENCE
int c = a;  //deep - copies VALUE
++a;

Результат:

a is 11  
*b is 11  
c is 10

Ответ 2

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

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

Ответ 3

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

Object B = A;

Глубокую копию можно сделать, получив свойства объекта A и поместив их в новый объект B.

Object B = new Object(A.getProperty1(), A.getProperty2()...);

Это влияет на поведение программы в том случае, если вы делаете мелкую копию и выполняете над ней задачу, которая затрагивает все мелкие копии объекта. Если вы внесете изменения в глубокую копию, будет затронута только эта копия. Надеюсь, это достаточно подробно для вас.

Ответ 4

Документ документов docs Calendar.clone 1.6: "Создает и возвращает копию этого объекта". Буквальная мелкая копия, указанная в Object.clone, не имеет смысла. Java использует термин "мелкая копия" в довольно типичном смысле.

Ответ 5

Это ошибка в документации. Я не вижу, как все, что делает метод Android Calendar.clone, соответствует типичному определению (на Java или в противном случае) "мелкой копии".

Ответ 6

Где вы получаете эту документацию?

Официальные документы Java 6 на java.sun.com просто Calendar.clone() возвращают копию объекта. Не упоминается мелкий.

В более общем плане, мелкая копия на Java - это та, где вы получаете новую ссылку на объект, но новый объект удерживает (прямо или косвенно) ссылки на данные в оригинале.

Например:

class MyClass{
  private List<Integer> innerList;

  public MyClass(List<Integer> list) { innerList = list; }

  //Some code...

  public Object clone(){
    return new MyClass(innerList);
  }
}

возвращает неглубокую копию в свой клон().

Ответ 7

Неглубокая копия просто копирует ссылку на объект в целевую ссылку. Он не создает новый объект в куче. По умолчанию Java выполняет мелкое клонирование с использованием функции clone().

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

Ответ 8

Прежде всего, Javadoc из ArrayList несколько ошибочен, если мы говорим об одномерных массивах, так как он использует метод copyOf в массивах. Итак, clone() возвращает одномерную копию, по крайней мере с 1,5 (я еще не тестировал)! Итак, что "мелкое" означает в Java: одномерный

Вы можете прочитать больше здесь: http://www.javapractices.com/topic/TopicAction.do?Id=3. Таким образом, clone() не является мелкой копией! Если вам нужна настоящая мелкая копия одномерного массива, просто укажите ее:

Array a = new Array();
Array b = a;                    //a is only a shallow copy, nice for synchronisation

Массивы на Java сложны, также потому, что Java выполняет передачу по значению, но значения массивов - это только их указатели! С другой стороны, это позволяет нам синхронизировать объекты, что очень важно. Тем не менее, есть некоторые проблемы, если вы используете массивы в массивах (или ArrayLists), потому что clone() из массива контейнеров (или ArrayList) не будет копировать их значения, а только их ссылки! Таким образом, вы просто не должны помещать массивы в массив, вы должны иметь дело только с объектами в массиве!

И Javadoc трудно понять иногда, поэтому попробуйте тестирование...

Удачи!

Ответ 9

В мелкой копии объект клона имеет копию примитивных значений, но ссылки на объекты ссылаются на те же объекты, что и исходная копия. Мелкие копии имеют значительный недостаток, клонированный объект и оригинальная копия относятся к одному и тому же адресу. Любое изменение, которое клонированный объект делает в объекте адреса, также будет отражено в оригинальной копии, что является нежелательным поведением. Нам действительно нужны две отдельные копии пользовательского объекта. Глубокое копирование приходит на помощь для такого рода ситуаций.

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

Здесь вы можете посмотреть рабочий пример: https://codingninjaonline.com/2017/11/09/deep-vs-shallow-copy/

Ответ 10

Мелкая Копия: В этом клонировании любые изменения в Клонированном Объекте отражаются также в Исходном Объекте.

Deep Copy: при этом клонировании выделяется отдельная клонированная память, что означает, что любые изменения в клонированном объекте не будут отражены в исходном объекте.

Ответ 11

МАЛЕНЬКАЯ КОПИЯ ПРОХОДИТ... ГЛУБОКАЯ КОПИЯ - ПРОШЛОЕ ЗНАЧЕНИЕ… Контекст отличается, но процесс точно такой же. Прежде всего помните, что при вызове метода Java примитивы передаются по значению, а объекты - по ссылке (в других языках объекты также могут передаваться по значению). Теперь в Java, когда вызывающая сторона передает примитив вызываемому методу, вызываемый метод просто клонирует его как новую локальную переменную, которая является глубокой копией. Хотя, если объект передается, вызываемый метод создает новую локальную ссылку на тот же объект, который является мелкой копией. Если вы понимаете вызов, вы понимаете глубокое/мелкое копирование & наоборот.