it-roy-ru.com

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

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

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

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

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

47
Will

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

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
70
KitsuneYMG

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

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

11
Chathuranga Chandrasekara

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

Object B = A;

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

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

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

5
mnuzzo

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

3
Tom Hawtin - tackline

Кажется, это ошибка в документации. Я не вижу, как что-либо, что делает метод Android Calendar.clone, соответствует типичному определению (в Java или иным образом) «мелкой копии».

2
jsight

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

Официальные документы по 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);
  }
}

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

1
Kevin Montrose

Прежде всего, Javadoc ArrayList несколько ошибочен, если мы говорим об одномерных массивах, так как он использует метод copyOf в Arrays. Поэтому 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 иногда трудно понять, так что попробуйте протестировать ...

Повеселись!

0
mark

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

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

Вы можете взглянуть на рабочий пример по этому адресу здесь: https://codingninjaonline.com/2017/11/09/deep-vs-shallow-copy/

0
pndey

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

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

0
Akanksha