2009-05-06 4 views
61

Почему Java не поддерживает конструктор копирования, как в C++?Почему Java не имеет конструктора копирования?

+0

Это отличные объяснения, благодаря всем! – Cuga

+0

Также читайте «Что случилось с конструкторами копирования? Зачем использовать интерфейс Clonable?» http://stackoverflow.com/questions/388304/whats-wrong-with-copy-constructors-why-use-cloneable-interface –

ответ

117

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 он просто копирует ссылку . Состояние объекта не копируется, поэтому неявное обращение к конструктору копирования бессмысленно.

И это все, что есть на самом деле.

+18

+1. В то время как остальные из нас были напуганы об иерархиях объектов, вы перешли прямо к синтаксису и, вероятно, ответили на вопрос * реального * OP, пока вы это делали. –

+1

Это отличное объяснение. Спасибо! – Cuga

+1

Возможно, вы захотите отредактировать задание; вы назначаете b2 себе. Кроме того, «statemen tlike» имеет место в неправильном месте. –

1

Угадайте, что они решили, что вы можете просто сделать метод clone()?

8

Я думаю, что ответ на этот вопрос очень интересный.

Во-первых, я считаю, что в Java все объекты находятся в куче, и пока у вас нет указателей, у вас есть «Ссылки». В ссылках есть копия symantics, и Java внутренне отслеживает количество ссылок, чтобы сборщик мусора знал, что можно избавиться.

Поскольку вы только получаете доступ к объектам с помощью копируемых ссылок, фактическое количество раз, когда вам нужно скопировать объект, значительно уменьшается (например, на C++ просто передача объекта функции (по значению) приводит к тому, что новые объекты копируются построенный, в Java передается только ссылка на объект). Дизайнеры, вероятно, полагали, что для остальных применений будет достаточно clone().

 

+2

Согласен. Конструктор копирования действительно решает проблемы управления памятью на C++. – alphazero

+0

Downvoted, потому что: * Java не использует семантику копирования (для объектов). Передача объекта вокруг не клонирует или не копирует объект, а также не изменяет количество ссылок - он просто передает ссылку. * Слишком много путаницы между семантикой копирования и фактом копирования ссылки на этот объект. – Arafangion

+0

В C++ вы должны передавать эти объекты указателем или ссылкой, чтобы минимизировать избыточное копирование. Это не проблема управления памятью, это просто (небольшие) синтаксические различия в языках, когда вы хотите сделать глубокую копию объекта. –

2

Это только мое мнение (я уверен, что есть обоснованный ответ)

Конструкторы копирования в C++ в основном используется при отправке или возвращать экземпляры классов по значению, так как это когда конструктор копирования прозрачно активирован.

Поскольку в Java все возвращается по ссылке, а виртуальная машина ориентирована на динамическое распределение, на самом деле не было оправдания сложностей конструктора копирования.

Кроме того, поскольку все по ссылке, разработчику часто приходилось предоставлять свою собственную реализацию и решение о том, как клонировать поля.

0

Это как будто. Когда мелкие копии в порядке, у вас есть [clone()] (http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html#clone()), и когда их нет, вам нужно реализовать глубокую копию, как C++.

Единственное существенное отличие состоит в том, что это заводский метод, а не собственный конструктор , но с точки зрения гибкости и тестируемости это, вероятно, хорошо.

0

Я не очень программист на C++, но, похоже, я помню правило о «трех амигах» - конструкторе копирования, операторе присваивания и деструктор.Если у вас его есть, то вам, вероятно, понадобятся все три.

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

+0

Не совсем. В C++ это больше похоже: если вам нужен один из трех (скажем, конструктор копирования), то вам, скорее всего, понадобятся и другие два, хотя вы не можете этого понять в то время. –

+1

Кроме того, если они вам не нужны, вы должны объявить их закрытыми и не выполнять их.Это заставит компилятор заменить свою собственную «мелкую» копию ... – dicroce

13

От Bruce Eckel:

Почему [конструктор копирования] работает в C++, а не Java?

Конструктор копирования является фундаментальной частью C++, так как он автоматически создает локальную копию объекта. Тем не менее приведенный выше пример доказывает, что он не работает для Java. Зачем? В Java все, что мы манипулируем, это дескриптор , в то время как на C++ вы можете иметь дескрипторных объектов, и вы также можете обходить объекты напрямую. Это то, что конструктор копии C++ предназначен для: когда вы хотите взять объект и передать его по значению, таким образом, дублирует объект. Поэтому он работает отлично в C++, но вы должны держать в умом, что эта схема не работает в Java, , поэтому не используйте ее.

(я рекомендую прочитать всю страницу - на самом деле, начать here вместо этого.)

-1

Java имеет скопировать Конструктор
Примечания: Вместо дема d2 = новый демо (d1), вы можете написать дема d2 = d1
Основного различия в ч/б два
демы d2 = новых демонстрационные (d1) означает, создается новый объект, и это выделенная память Но
демонстрационных d2 = d1 означает ссылаться только переменный создаются , который использует один и тот же адрес памяти объекта d1 и, следовательно, d2 не выделено отдельная память.

Синтаксис конструктора копирования:
Ниже Пример первый конструктор копирования очень просто :))
имя_класса (интермедиат DataField) // Простой конструктор
{
this.datafield = DataField;
}

имя_класса (имя_класса объект)
{
DataField = объект.DataField; // См ниже пример
}
Теперь для вызова
{

имя_класса OBJ = новый Classname();

имя_класса anotherObject = OBJ; // или имя_класса anotherObject = новый имя_класса (объект)

}

 

class demo 
{ 
    private int length; 

    private int breadth; 

    private int radius; 

    demo(int x,int y) 

    { 
     length=x; 
     breadth=y; 
    } 
    int area() 
    { 
     return length*breadth; 
    } 

    //Copy Constructor 
    demo(demo obj) 
    { 
     length=obj.length; 
     breadth=obj.breadth; 
    } 


    public static void main(String args[]) 
    { 
     demo d1=new demo(5,6); 
     demo d2=new demo(d1);//Invokes Copy Constructure 
     System.out.println("Area for d1 object="+d1.area()); 
     System.out.println("Area for d2 object="+d2.area()); 

    } 
} 

0

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

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

Представьте себе, что Java имеет такое поведение. Любой класс, у которого есть поля, которые являются объектами (читай: по сути, все они), будет иметь неправильное поведение, и вам нужно будет переопределить его самостоятельно. В 99% случаев вы никому не помогли. Кроме того, вы просто создали тонкую ловушку для себя - представьте, что вы случайно забыли переопределить конструктор копии по умолчанию. Если он был создан по умолчанию, и вы пытаетесь его использовать, компилятор вообще не будет жаловаться, но ваша программа будет плохо себя вести во время выполнения.

Даже если они сделали конструктор копии по умолчанию, который выполняет глубокую копию, я не уверен, что это было бы особенно полезно. Мало того, что вы, как правило, выполняете меньше копий на Java, чем C++, но вы не всегда хотите, чтобы скопировать поле.

Объекты, которыми вы владеете, и объекты, на которых вы держите ссылки, потому что они вам нужны, но не отвечают за, являются одинаковыми - просто поля. Собственность и заимствование не являются понятиями первого класса. Для объектов, которые у вас есть, вы хотите их глубоко скопировать (если они не являются неизменными, и в этом случае вам не следует беспокоиться), а для объектов, на которые вы просто держите ссылку, вы хотите скопировать ссылку.

Я бы сказал, что конструктор копирования, который просто бездумно глубоко копирует все, не подходит для многих классов. Конечно, более чем мелкое копирование по умолчанию.