Компилятор хочет, чтобы вы это записывали:
private static List<String> list = new ArrayList<String>();
, потому что в противном случае вы могли бы добавить любой тип, который вам нравится, в list
, делая создание как new ArrayList<String>()
бессмысленным. Java generics - это только функция времени компиляции, поэтому объект, созданный с помощью new ArrayList<String>()
, с радостью примет Integer
или JFrame
элементы, если они назначены ссылке «raw type» List
- сам объект ничего не знает о какие типы он должен содержать, только компилятор делает.
Мелкие копии дублируют как можно меньше. Неглубокая копия коллекции - это копия структуры коллекции, а не элементов. С неглубокой копией две коллекции теперь разделяют отдельные элементы.
Глубокие копии дублируют все. Глубокая копия коллекции - это две коллекции, в которых дублируются все элементы в исходной коллекции.
Неглубокое клонирование: определение: «Неглубокая копия объекта копирует« основной »объект, но не копирует внутренние объекты». Когда пользовательский объект (например, Employee) имеет только примитивные переменные типа String, вы используете Shallow Cloning.
Employee e = new Employee(2, "john cena");
Employee e2=e.clone();
Вы возвращаете super.clone();
в метод overridden clone (), и ваша работа завершена.
Глубокое клонирование: определение: «В отличие от мелкой копии глубокая копия полностью независимая копия объекта ». Значит, если объект Employee имеет другой пользовательский объект:
Employee e = new Employee(2, "john cena", new Address(12, "West Newbury", "Massachusetts");
Затем вам нужно написать код, чтобы клонировать объект «Адрес», а также в методе overridden clone (). В противном случае объект Address не будет клонировать и вызывает ошибку при изменении значения адреса в клонированном объекте Employee, который также отражает исходный.
Добавление ко всем приведенным выше определениям, еще одна и наиболее часто используемая глубокая копия, находится в конструкторе копирования (или перегружает присваивающий оппортер) класса.
Неверная копия -> когда вы не предоставляя конструктор копирования. Здесь копируется только объект, но не все члены класса копируются.
Deep copy -> это когда вы решили реализовать конструктор копирования или перегрузку в своем классе и разрешить копирование всех членов класса.
MyClass& MyClass(const MyClass& obj) // copy constructor for MyClass
{
// write your code, to copy all the members and return the new object
}
MyClass& operator=(const MyClass& obj) // overloading assignment operator,
{
// write your code, to copy all the members and return the new object
}
Я не видел здесь короткого, легко понятного ответа, поэтому я попробую.
С мелкой копией любой объект, на который указывает источник, также указывает на (так, чтобы никакие ссылочные объекты не копировались).
С глубокой копией копируется любой объект, на который указывает источник, и копия указывается адресатом (так что теперь будет 2 каждого ссылочного объекта). Это повторяет дерево объектов.
var source = { firstName="Jane", lastname="Jones" };
var shallow = ShallowCopyOf(source);
var deep = DeepCopyOf(source);
source.lastName = "Smith";
WriteLine(source.lastName); // prints Smith
WriteLine(shallow.lastName); // prints Smith
WriteLine(deep.lastName); // prints Jones
Ширина и глубина; подумайте в терминах дерева ссылок с вашим объектом в качестве корневого узла.
Shallow:
[/g0] [/g1] [/g2]
Переменные A и B относятся к разным областям памяти, когда B присваивается A, две переменные относятся к той же области памяти. Более поздние модификации содержимого либо мгновенно отражаются в содержимом другого, так как они содержат содержимое.
Глубокий:
[/g3] [/g4] [/g5]
Переменные A и B относятся к разным областям памяти, когда B присваивается A значениям в области памяти, которые A указывает на копирование в область памяти, чтобы который B указывает. Более поздние модификации содержимого либо остаются уникальными для A или B; содержимое не используется.
«ShallowCopy» указывает на то же место в памяти, что и «Источник». «DeepCopy» указывает на другое место в памяти, но содержимое одного и того же.
{Представьте себе два объекта: A и B того же типа _t (относительно C ++), и вы думаете о неглубоко / глубоком копировании A-B}
Неверное копирование: просто делает копию ссылку на A в B. Подумайте об этом как копию адреса A. Таким образом, адреса A и B будут одинаковыми, то есть они будут указывать на то же место памяти, то есть на содержимое.
Глубокая копия: просто делает копию всех членов A, выделяет память в другое место для B, а затем назначает скопированные элементы B для достижения глубокой копии. Таким образом, если A становится несуществующим, B все еще действует в памяти. Правильный термин для использования будет клонированием, где вы знаете, что оба они абсолютно одинаковы, но все же разные (т. Е. Хранятся как два разных объекта в пространстве памяти). Вы также можете предоставить свою клон-обертку, где вы можете выбрать через список включения / исключения, какие свойства выбрать во время глубокой копии. Это довольно распространенная практика при создании API-интерфейсов.
Вы можете выбрать «Мелкая копия ONLY_IF», в которой вы понимаете вовлеченные ставки. Когда у вас есть огромное количество указателей для работы на C ++ или C, выполнение мелкой копии объекта ДЕЙСТВИТЕЛЬНО - плохая идея.
EXAMPLE_OF_DEEP COPY_ Примером является то, что когда вы пытаетесь выполнить обработку изображений и распознавание объектов, вам нужно замаскировать «Irrelevant and Repeating Motion» из ваших областей обработки. Если вы используете указатели изображений, у вас может быть спецификация для сохранения этих изображений масок. СЕЙЧАС ... если вы сделаете мелкую копию изображения, когда ссылки указателя будут убиты из стека, вы потеряли ссылку и ее копию, то есть в какой-то момент будет ошибка времени выполнения. В этом случае вам нужна глубокая копия вашего изображения с помощью CLONING. Таким образом, вы можете получить маски в случае, если они вам понадобятся в будущем.
EXAMPLE_OF_SHALLOW_COPY Я не очень осведомлен по сравнению с пользователями в StackOverflow, поэтому не стесняйтесь удалять эту часть и ставить хороший пример, если вы может уточнить. Но я действительно думаю, что неплохо делать мелкую копию, если вы знаете, что ваша программа будет работать в течение бесконечного периода времени, т. Е. Непрерывная операция push-pop поверх стека с вызовами функций. Если вы демонстрируете что-то любителю или новичку (например, учебное пособие C / C ++), то, вероятно, все в порядке. Но если вы используете приложение, такое как система наблюдения и обнаружения, или система отслеживания сонара, вы не должны хранить мелкие копии своих объектов, потому что это рано или поздно убьет вашу программу.
Специально для разработчиков iOS:
Если B
является мелкой копией A
, то для примитивных данных это похоже на B = [A assign];
, а для объектов это похоже на B = [A retain]
;
B и A указывают на ту же ячейку памяти
Если B
является глубокой копией A
, то это похоже на B = [A copy];
B и A указывают на разные ячейки памяти
Адрес памяти B такой же, как у
B имеет такое же содержимое, как и A
В объектно-ориентированном программировании тип включает в себя набор полей-членов. Эти поля могут храниться либо по значению, либо по ссылке (т. Е. Указателю на значение).
В неглубокой копии создается новый экземпляр типа и значения копируются в новый экземпляр , Ориентировочные указатели также копируются точно так же, как и значения. Поэтому ссылки указывают на исходные объекты. Любые изменения в элементах, которые хранятся по ссылке, отображаются как в оригинале, так и в копии, поскольку копия объекта ссылки не была сделана.
В глубокой копии поля, которые хранятся по значению, копируются как и раньше, но указатели на объекты, хранящиеся по ссылке, не копируются. Вместо этого делается глубокая копия объекта, на который ссылается, и сохраняется указатель на новый объект. Любые изменения, внесенные в эти объекты, не будут влиять на другие копии объекта.
char * Source = "Hello, world.";
char * ShallowCopy = Source;
char * DeepCopy = new char(strlen(Source)+1);
strcpy(DeepCopy,Source);
«ShallowCopy» указывает на то же место в памяти, что и «Источник». «DeepCopy» указывает на другое место в памяти, но содержимое одного и того же.
Чтобы добавить немного больше для путаницы между мелкой копией и просто назначить новое имя переменной для списка.
«Скажем, у нас есть:
x = [
[1,2,3],
[4,5,6],
]
Это утверждение создает 3 списки: 2 внутренних списка и один внешний список. Ссылка на внешний список затем становится доступной под именем x.Если мы выполняем
y = x
, данные не копируются. У нас все еще есть те же 3 списка в памяти где-то все это делает внешний список доступным под именем y, в дополнение к его предыдущему имени x. Если мы делаем
y = list(x)
или
y = x[:]
Это создает новый список с тем же содержимым, что и x. Список x содержит ссылку на 2 внутренних списка, поэтому новый список также будет содержать ссылку на те же самые 2 внутренних списка. Только один список копируется - внешний список. есть 4 списка в памяти, два внутренних списка, внешний список и копия внешнего списка. Исходный внешний список доступен под именем x, а новый внешний список становится доступным под именем y.
Внутренние списки не были пестрая!
Если у вас есть двумерный (или более высокий) список или любая вложенная структура данных, и вы хотите создать полная копия всего, то вы хотите использовать функцию deepcopy () в модуле копирования. Ваше решение также работает для 2-D списков, как итерации над элементами во внешнем списке и делает копию каждого из них, а затем создает новый внешний список для всех внутренних копий ».
мелкая копия не создаст новую ссылку, но глубокая копия создаст новую ссылку. Вот программа для объяснения глубокой и мелкой копии
public class DeepAndShollowCopy {
int id;
String name;
List<String> testlist = new ArrayList<>();
/*
// To performing Shallow Copy
// Note: Here we are not creating any references.
public DeepAndShollowCopy(int id, String name, List<String>testlist)
{
System.out.println("Shallow Copy for Object initialization");
this.id = id;
this.name = name;
this.testlist = testlist;
}
*/
// To performing Deep Copy
// Note: Here we are creating one references( Al arraylist object ).
public DeepAndShollowCopy(int id, String name, List<String> testlist) {
System.out.println("Deep Copy for Object initialization");
this.id = id;
this.name = name;
String item;
List<String> Al = new ArrayList<>();
Iterator<String> itr = testlist.iterator();
while (itr.hasNext()) {
item = itr.next();
Al.add(item);
}
this.testlist = Al;
}
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Java");
list.add("Oracle");
list.add("C++");
DeepAndShollowCopy copy=new DeepAndShollowCopy(10,"Testing", list);
System.out.println(copy.toString());
}
@Override
public String toString() {
return "DeepAndShollowCopy [id=" + id + ", name=" + name + ", testlist=" + testlist + "]";
}
}
Копирование ararys:
Массив - это класс, что означает, что он является ссылочным типом, поэтому array1 = array2 приводит к двум переменным, которые ссылаются на один и тот же массив.
Но посмотрите на этот пример :
static void Main()
{
int[] arr1 = new int[] { 1, 2, 3, 4, 5 };
int[] arr2 = new int[] { 6, 7, 8, 9, 0 };
Console.WriteLine(arr1[2] + " " + arr2[2]);
arr2 = arr1;
Console.WriteLine(arr1[2] + " " + arr2[2]);
arr2 = (int[])arr1.Clone();
arr1[2] = 12;
Console.WriteLine(arr1[2] + " " + arr2[2]);
}
мелкий клон означает, что копируется только память, представленная клонированным массивом.
Если массив содержит объекты типа значения, значения копируются;
, если массив содержит ссылочный тип, копируются только ссылки - поэтому в результате есть два массива, члены которых ссылаются на одни и те же объекты.
Чтобы создать дублированный тип ссылки с копией, где необходимо дублировать, вы должны пройти через массив и клонировать каждый элемент вручную.
private void button1_Click(object sender, EventArgs e) { int[] arr1 = new int[]{1,2,3,4,5}; int[] arr2 = new int[]{6,7,8,9,0}; MessageBox.Show(arr1[2] + " " + arr2[2]); arr2 = arr1; MessageBox.Show(arr1[2] + " " + arr2[2]); arr1[2] = 12; MessageBox.Show(arr1[2] + " " + arr2[2]); }
– DeanOC
19 December 2012 в 23:38
Неверная копия: & nbsp; копирует значения элементов из одного объекта в другой.
Глубокая копия: & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; копирует значения элементов из одного объекта в другой. & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;; & nbsp; .
Пример:
class String
{
int size;
char* data;
};
String s1("Ace"); // s1.size = 3 s1.data=0x0000F000
String s2 = shallowCopy(s1);
// s2.size =3 s2.data = 0X0000F000
String s3 = deepCopy(s1);
// s3.size =3 s3.data = 0x0000F00F
// (With Ace copied to this location.)
struct sample
{
char * ptr;
}
void shallowcpy(sample & dest, sample & src)
{
dest.ptr=src.ptr;
}
void deepcpy(sample & dest, sample & src)
{
dest.ptr=malloc(strlen(src.ptr)+1);
memcpy(dest.ptr,src.ptr);
}
Представьте, что существуют два массива, называемые arr1 и arr2.
arr1 = arr2; //shallow copy
arr1 = arr2.clone(); //deep copy
Неглубокое копирование создает новый объект, а затем копирует нестатические поля текущего объекта в новый объект. Если поле является типом значения -> выполняется побитовая копия поля; для ссылочного типа -> ссылка копируется, но упомянутый объект не является; поэтому исходный объект и его клон относятся к одному и тому же объекту.
Глубокая копия создает новый объект и затем копирует нестатические поля текущего объекта в новый объект. Если поле является типом значения -> выполняется побитовая копия поля. Если поле является ссылочным типом -> выполняется новая копия упомянутого объекта. Классы, подлежащие клонированию, должны быть помечены как [Serializable].
Конструктор копирования используется для инициализации нового объекта с ранее созданным объектом того же класса. По умолчанию компилятор написал мелкую копию. Мелкая копия отлично работает, когда динамическое распределение памяти не задействовано, поскольку при распределении динамической памяти оба объекта указывают на одну и ту же ячейку памяти в куче, поэтому для удаления этой проблемы мы написали глубокую копию, чтобы оба объекта имели свою собственную копию атрибутов в памяти. Чтобы прочитать подробности с полными примерами и пояснениями, вы можете увидеть конструкторы C ++ .
В простых терминах «Мелкая копия» похожа на Call By Reference, а Deep Copy похожа на Call By Value
. В Call By Reference, как формальные, так и фактические параметры функции относятся к одной и той же памяти местоположение и значение.
В разделе «Вызов по значению» как формальные, так и фактические параметры функций относятся к разным ячейкам памяти, но имеют одинаковое значение.
Взято из [blog]: http://sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html
Глубокая копия предполагает использование содержимого одного объекта для создания другого экземпляра того же класса. В глубокой копии оба объекта могут содержать одну и ту же информацию, но целевой объект будет иметь свои собственные буферы и ресурсы. уничтожение любого объекта не повлияет на оставшийся объект. Перегруженный оператор присваивания создаст глубокую копию объектов.
Неглубокая копия включает в себя копирование содержимого одного объекта в другой экземпляр того же класса, создавая таким образом зеркальное изображение. Благодаря прямому копированию ссылок и указателей два объекта будут иметь одно и то же содержимое, содержащее внешний контент другого объекта, чтобы быть непредсказуемым.
Объяснение:
Используя конструктор копирования, мы просто копируем элемент данных принимает член. Этот метод копирования называется мелкой копией. Если объект является простым классом, состоящим из встроенных типов и без указателей, это будет приемлемым. Эта функция будет использовать значения и объекты, и ее поведение не будет изменено с помощью мелкой копии, копируются только адреса указателей, которые являются членами, а не значение, на которое указывает адрес. Значения данных объекта затем будут непреднамеренно изменены функцией. Когда функция выходит за пределы области видимости, копия объекта со всеми его данными удаляется из стека.
Если объект имеет какие-либо указатели, необходимо выполнить глубокую копию. С глубокой копией объекта память выделяется для объекта в свободном хранилище, а отмеченные элементы копируются. Для объектов, возвращаемых функцией, используется глубокая копия.
Что такое мелкая копия?
Неглубокая копия - это бит-копия объекта. Создается новый объект, который имеет точную копию значений в исходном объекте. Если какое-либо из полей объекта является ссылкой на другие объекты, копируются только ссылочные адреса, т. Е. Копируется только адрес памяти. [/g1]
На этом рисунке MainObject1
есть поля field1
типа int и ContainObject1
типа ContainObject
. Когда вы делаете мелкую копию MainObject1
, MainObject2
создается с field2
, содержащим скопированное значение field1
и все еще указывая на ContainObject1
. Обратите внимание, что поскольку field1
имеет примитивный тип, его значение копируется в field2
, но поскольку ContainedObject1
является объектом, MainObject2
все еще указывает на ContainObject1
. Поэтому любые изменения, сделанные в ContainObject1
в MainObject1
, будут отражены в MainObject2
.
Теперь, если это мелкая копия, давайте посмотрим, что такое глубокая копия?
Что такое Deep Copy?
Глубокая копия копирует все поля и создает копии динамически выделенной памяти, на которые указывают поля. Глубокая копия возникает, когда объект копируется вместе с объектами, к которым он относится. [/g2]
На этом рисунке MainObject1 имеют поля типа field1
типа int и ContainObject1
типа ContainObject
. Когда вы делаете глубокую копию MainObject1
, MainObject2
создается с field2
, содержащим скопированное значение field1
и ContainObject2
, содержащее скопированное значение ContainObject1
. Обратите внимание, что любые изменения, сделанные в ContainObject1
в MainObject1
, не будут отображаться в MainObject2
.
Глубокая копия
Глубокая копия копирует все поля и создает копии динамически выделенной памяти, на которые указывают поля. Глубокая копия возникает, когда объект копируется вместе с объектами, к которым он относится.
Неверная копия
Неглубокая копия - это бит-мудрая копия объекта. Создается новый объект, который имеет точную копию значений в исходном объекте. Если какое-либо из полей объекта является ссылкой на другие объекты, копируются только ссылочные адреса, т. Е. Копируется только адрес памяти.
Неглубокая копия создает новый составной объект и вставляет его ссылки в исходный объект.
В отличие от мелкой копии, deepcopy создает новый составной объект, а также вставляет копии исходных объектов исходного составного объекта .
Давайте возьмем пример.
import copy
x =[1,[2]]
y=copy.copy(x)
z= copy.deepcopy(x)
print(y is z)
Выше кода печатает FALSE.
Посмотрим, как.
Оригинальный составной объект x=[1,[2]]
(называемый соединением, поскольку он имеет объект внутри объекта (начало))
, как вы можете видеть на изображении, есть список внутри list.
Затем мы создаем мелкую копию с помощью y = copy.copy(x)
. Что здесь делает python, он создаст новый составной объект, но объекты внутри них будут указывать на объекты orignal.
На изображении у него есть создала новую копию для внешнего списка. но внутренний список остается таким же, как и исходный.
Теперь мы создаем его глубокую копию, используя z = copy.deepcopy(x)
. то, что здесь делает python, он создаст новый объект для внешнего списка, а также для внутреннего списка. как показано на изображении ниже (красный выделен).
В конце кода печатается False
, так как y и z не являются одними и теми же объектами.
HTH.
Я хотел бы привести пример, а не формальное определение.
var originalObject = {
a : 1,
b : 2,
c : 3,
};
Этот код показывает мелкую копию:
var copyObject1 = originalObject;
console.log(copyObject1.a); // it will print 1
console.log(originalObject.a); // it will also print 1
copyObject1.a = 4;
console.log(copyObject1.a); //now it will print 4
console.log(originalObject.a); // now it will also print 4
var copyObject2 = Object.assign({}, originalObject);
console.log(copyObject2.a); // it will print 1
console.log(originalObject.a); // it will also print 1
copyObject2.a = 4;
console.log(copyObject2.a); // now it will print 4
console.log(originalObject.a); // now it will print 1
Этот код показывает глубокую копию:
var copyObject2 = Object.assign({}, originalObject);
console.log(copyObject2.a); // it will print 1
console.log(originalObject.a); // it will also print 1
copyObject2.a = 4;
console.log(copyObject2.a); // now it will print 4
console.log(originalObject.a); // !! now it will print 1 !!
Просто для легкого понимания вы можете следовать этой статье: https://www.cs.utexas.edu/~scottm/cs307/handouts/deepCopying.htm
< hr>Неверная копия:
Глубокая копия:
Неверная копия. Справочная переменная внутри исходных и неглубококопированных объектов имеет ссылку на общий объект.
Глубинная копия. Справочная переменная внутри оригинальных и глубоко скопированных объектов имеет ссылку на другой объект.
clone всегда делает мелкую копию.
blockquote>public class Language implements Cloneable{ String name; public Language(String name){ this.name=name; } public String getName() { return name; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } }
следующий класс -
public static void main(String args[]) throws ClassNotFoundException, CloneNotSupportedException{ ArrayList<Language> list=new ArrayList<Language>(); list.add(new Language("C")); list.add(new Language("JAVA")); ArrayList<Language> shallow=(ArrayList<Language>) list.clone(); //We used here clone since this always shallow copied. System.out.println(list==shallow); for(int i=0;i<list.size();i++) System.out.println(list.get(i)==shallow.get(i));//true ArrayList<Language> deep=new ArrayList<Language>(); for(Language language:list){ deep.add((Language) language.clone()); } System.out.println(list==deep); for(int i=0;i<list.size();i++) System.out.println(list.get(i)==deep.get(i));//false }
OutPut выше будет -
false true true
false false false
blockquote>Любое изменение, сделанное в исходном объекте, будет отражено в мелком объекте, а не в глубоком объекте.
list.get(0).name="ViSuaLBaSiC"; System.out.println(shallow.get(0).getName()+" "+deep.get(0).getName());
OutPut- ViSuaLBaSiC C
Чтобы добавить другие ответы,