Почему в Java нет конструктора копирования?
Почему Java не поддерживает конструктор копирования, как в C++?
9 ответов
Java делает. Они просто не вызваны неявно, как в C++, и я подозреваю, что это ваш реальный вопрос.
Во-первых, конструктор копирования - это не более чем:
public class Blah {
private int foo;
public Blah() { } // public no-args constructor
public Blah(Blah b) { foo = b.foo; } // copy constructor
}
Теперь C++ будет неявно вызывать конструктор копирования с помощью следующего предложения:
Blah b2 = b1;
Клонирование / копирование в этом случае просто не имеет смысла в Java, потому что все b1 и b2 являются ссылками, а не объектами-значениями, как в C++. В C++ это утверждение создает копию состояния объекта. В Java это просто копирует ссылку. Состояние объекта не копируется, поэтому неявный вызов конструктора копирования не имеет смысла.
И это все, что нужно на самом деле.
От Брюса Экеля:
Почему [конструктор копирования] работает на C++, а не на Java?
Конструктор копирования является фундаментальной частью C++, поскольку он автоматически создает локальную копию объекта. Тем не менее, приведенный выше пример доказывает, что он не работает для Java. Зачем? В Java все, чем мы манипулируем, является дескриптором, в то время как в C++ у вас могут быть объекты, похожие на дескрипторы, и вы также можете передавать объекты напрямую. Вот для чего нужен конструктор копирования C++: когда вы хотите взять объект и передать его по значению, дублируя объект. Так что он отлично работает в C++, но вы должны иметь в виду, что эта схема не работает в Java, поэтому не используйте ее.
(Я рекомендую прочитать всю страницу - на самом деле, вместо этого начните здесь.)
Я думаю, что ответ на это очень интересно.
Во-первых, я считаю, что в Java все объекты находятся в куче, и, хотя у вас нет указателей, у вас есть "Ссылки". Ссылки имеют симметрию копирования, а java внутренне отслеживает количество ссылок, чтобы сборщик мусора знал, от чего можно избавиться.
Поскольку доступ к объектам осуществляется только через копируемые ссылки, фактическое количество раз, необходимое для копирования объекта, значительно сокращается (например, в C++ простая передача объекта в функцию (по значению) приводит к созданию новых объектов, копируемых в Java). передается только ссылка на объект). Дизайнеры, вероятно, полагали, что clone() будет достаточно для оставшегося использования.
Это только мое мнение (я уверен, что есть оправданный ответ)
Конструкторы копирования в C++ в первую очередь полезны, когда вы отправляете или возвращаете экземпляры классов по значению, поскольку именно тогда конструктор копирования прозрачно активируется.
Поскольку в Java все возвращается по ссылке, а виртуальная машина ориентирована на динамическое размещение, сложностей конструктора копирования на самом деле не было.
Кроме того, поскольку все по ссылке, разработчику часто приходится предоставлять собственную реализацию и решение о том, как клонировать поля.
Думаю, они решили, что вместо этого можно создать метод clone()?
Это вроде как. Когда с мелкими копиями все в порядке, у вас есть [clone ()] ( http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html и когда они нет Вы должны реализовать глубокую копию, как C++.
Единственное существенное отличие состоит в том, что это скорее фабричный метод, чем собственно конструктор, но с точки зрения гибкости и тестируемости это, вероятно, хорошая вещь.
Я не большой программист на C++, но мне кажется, что я помню правило о "трех amigos" - конструкторе копирования, операторе присваивания и деструкторе. Если у вас есть один, то вам, вероятно, нужны все три.
Так что, возможно, без деструктора в языке, они не хотели включать конструктор копирования? Просто предположение.
Ну, это может. Это просто не создается неявно. Если бы мне пришлось угадывать, это, вероятно, связано с тем, что объекты Java всегда размещаются в куче.
В C++ конструктором копирования по умолчанию является мелкая копия для каждого члена. Если классу принадлежит память, выделенная в куче (через необработанный указатель), это приведет к тому, что копия будет делиться внутренними данными с оригиналом, а это не то, что вам нужно.
Представьте на мгновение, что у Java такое поведение. Любой класс, у которого есть поля, которые являются объектами (читай: по сути, все они), будет иметь неправильное поведение, и вам придется переопределить его самостоятельно. В 99% случаев вы никого не спасли. Кроме того, вы только что создали тонкую ловушку для себя - представьте, что вы случайно забыли переопределить конструктор копирования по умолчанию. Если он был сгенерирован по умолчанию, и вы пытаетесь его использовать, компилятор вообще не будет жаловаться, но ваша программа будет плохо себя вести во время выполнения.
Даже если бы они сделали конструктор копирования по умолчанию, который выполняет глубокое копирование, я не уверен, что это будет особенно полезно. В любом случае вы не только выполняете меньше копий в Java, чем в C++, но не всегда хотите глубоко копировать поле.
Объекты, которыми вы владеете, и объекты, на которые вы ссылаетесь, потому что они вам нужны, но не несут ответственности, - это одно и то же - просто поля. Собственность и заимствование не являются первоклассными понятиями. Для объектов, которыми вы владеете, вы захотите глубоко копировать их (если они не являются неизменяемыми, в этом случае вам не следует беспокоиться), а для объектов, на которые вы просто ссылаетесь, вы хотите скопировать ссылку.
Я бы сказал, что конструктор копирования, который просто бездумно копирует все, также не подходит для многих классов. Конечно, больше, чем поверхностное копирование по умолчанию.
Java есть Копировать Конструктор
Примечание: вместо demo d2=new demo(d1) вы можете написать demo d2=d1
Основное отличие ч / б два
demo d2=new demo(d1) означает, что новый объект создан и ему выделена память
demo d2=d1 означает, что создается только ссылочная переменная, которая использует тот же адрес памяти объекта d1 и, следовательно, d2 не выделяет разделенную память.
Синтаксис конструктора копирования:
Смотрите ниже Пример первого Копировать конструктор очень просто:))
classname (int datafield) // Простой конструктор
{
this.datafield = DataField;
}
имя класса (объект имени класса)
{
datafield = object.datafield; // см. пример ниже
}
Теперь для вызова
{
имя класса obj = новое имя класса ();
имя класса anotherObject=obj;// или имя класса anotherObject = новое имя класса (obj)
}
демонстрация класса { частная длина int; частный в ширину; частный внутренний радиус; демо (int x,int y) { длина = х; Широта = у; } int area() { возвращаемая длина * ширина; } // Копировать конструктор демо (demo obj) { длина =obj.length; Широта =obj.breadth; } public static void main(строковые аргументы []) { демо d1= новое демо (5,6); demo d2=new demo(d1);// вызывает структуру копирования System.out.println("Область для объекта d1="+d1.area()); System.out.println("Область для объекта d2 ="+d2.area()); } }