В Java что такое мелкая копия?
java.util.Calendar.clone() возвращает "... новый календарь с такими же свойствами" и возвращает "мелкую копию этого календаря".
Это не похоже на мелкую копию, как здесь ответили на SO. Этот вопрос помечен как независимый от языка, Java, кажется, не следует определению, не зависящему от языка. Проходя по коду, я замечаю, что структура и элементы копируются в этот новый объект, а не только в независимую от языка структуру.
В Java что такое мелкая копия?
Чем он отличается от глубокой копии Java (если таковая существует)?
9 ответов
Мелкая копия просто копирует значения ссылок в классе. Глубокая копия копирует значения. дано:
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
Мелкая копия - это просто набор указателей на одни и те же области памяти. На самом деле он не создает реальную копию, поэтому использование памяти ниже.
В случае глубокой копии создается точная копия сегмента памяти, и указатели устанавливаются на новые области памяти. Таким образом, теоретически потребление памяти должно быть в два раза в этом случае.
Мелкая копия - это копия ссылочного указателя на объект, тогда как глубокая копия - это копия самого объекта. В Java объекты хранятся в фоновом режиме, с чем вы обычно взаимодействуете при работе с объектами - это указатели. Имена переменных указывают на область памяти объекта. Мелкая копия создается, когда вы устанавливаете одну переменную равной другой, например:
Object B = A;
Глубокая копия может быть получена путем получения свойств объекта A и помещения их в новый объект B.
Object B = new Object(A.getProperty1(), A.getProperty2()...);
Это влияет на поведение программы в том смысле, что если вы делаете мелкую копию и выполняете на ней задачу, это влияет на все мелкие копии объекта. Если вы вносите изменения в глубокую копию, это влияет только на эту копию. Я надеюсь, что это достаточно подробно для вас.
Документ 1.6 Calendar.clone
as "Создает и возвращает копию этого объекта." Буквально мелкая копия, как указано Object.clone
не имеет никакого смысла. Java использует термин "мелкая копия" в довольно типичном смысле.
МАЛЕНЬКАЯ КОПИЯ - ПРОХОДЯЩАЯ ПОЗНАЧЕНИЕ... ГЛУБОКАЯ КОПИЯ - ПРОХОДНАЯ ЗНАЧЕНИЕ... Контекст другой, но процесс точно такой же. Сначала помните, что при вызове метода Java примитивы передаются по значению, а объекты передаются по ссылке (в других языках объекты также могут передаваться по значению). Теперь, в Java, когда вызывающий объект передает примитив вызываемому методу, вызываемый метод просто клонирует его как новую локальную переменную, которая является глубокой копией. В то время как, если объект передан, вызываемый метод создаст только новую локальную ссылку на тот же объект, которая является неглубокой копией. Если вы понимаете призыв, вы понимаете глубокое / поверхностное копирование и наоборот.
Кажется, это ошибка в документации. Я не понимаю, как метод Android Calendar.clone соответствует типичному определению (в Java или иным образом) "мелкой копии".
В мелкой копии объект-клон имеет копию примитивных значений, но ссылки на объекты ссылаются на те же объекты, что и оригинальная копия. Мелкие копии имеют существенный недостаток, клонированный объект и оригинальная копия ссылаются на один и тот же адресный объект. Любое изменение, которое клонированный объект вносит в адресный объект, также будет отражено в оригинальной копии, что является нежелательным поведением. Что мы действительно хотели, так это две отдельные копии объекта пользователя. Глубокое копирование помогает нам в такой ситуации.
Глубокое копирование клонов не только примитивных значений, но и создание копий ссылок на объекты.
Вы можете посмотреть на рабочий пример по этому адресу здесь: https://codingninjaonline.com/2017/11/09/deep-vs-shallow-copy/
Мелкая Копия: В этом клонировании любые изменения в Клонированном Объекте отражаются также в Исходном Объекте.
Deep Copy: при этом клонировании выделяется отдельная клонированная память, что означает, что любые изменения в клонированном объекте не будут отражены в исходном объекте.
Где вы получаете эту документацию?
Официальные документы по 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);
}
}
возвращает неглубокую копию в свой клон ().
Мелкая копия просто копирует ссылку на объект в целевую ссылку. Он не создает новый объект в куче. По умолчанию Java выполняет поверхностное клонирование с использованием функции clone().
Чтобы получить новый объект в куче, необходимо выполнить глубокое клонирование, которое может быть реализовано с помощью сериализации и десериализации.
Прежде всего, 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 иногда трудно понять, так что попробуйте протестировать...
Повеселись!