Почему в Java нет конструктора копирования? - PullRequest
64 голосов
/ 06 мая 2009

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

Ответы [ 9 ]

130 голосов
/ 06 мая 2009

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

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

13 голосов
/ 06 мая 2009

С Брюс Экель :

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

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

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

9 голосов
/ 06 мая 2009

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

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

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

2 голосов
/ 06 мая 2009

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

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

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

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

1 голос
/ 06 мая 2009

Думаешь, они решили, что вместо этого можно создать метод clone ()?

0 голосов
/ 29 августа 2016

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

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

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

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

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

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

0 голосов
/ 08 июля 2013

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

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

имя класса (объект имени класса)
{
datafield = object.datafield; // см. пример ниже
}
Теперь для вызова
* * {Тысяча двадцать-один

classname obj = новое имя класса ();

имя класса anotherObject = obj; // или имя класса anotherObject = новое имя класса (obj)

}


 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 голосов
/ 06 мая 2009

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

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

0 голосов
/ 06 мая 2009

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...