Присвоение (*this)
в C ++ выполняет операцию копирования - обрабатывает объект как тип значения .
Java не использует концепцию типа значения для классов. Назначение объекта всегда по ссылке .
Чтобы скопировать объект, как если бы он был типом значения: Как скопировать объект в Java?
Терминология, используемая для Java, сбивает с толку: Является ли Java «передачей по ссылке» или «передачей по значению»
Ответ: Java передает ссылки по значению. (с здесь )
Другими словами, поскольку Java никогда не рассматривает не примитивы как типы значений, каждая переменная типа класса является ссылкой (фактически указателем).
Поэтому, когда я говорю, «назначение объекта всегда по ссылке», это может быть технически более точным для фразы, что «назначение объекта всегда значение ссылка».
Практическое значение различия, проведенного Java всегда , являющегося передачей по значению, воплощено в вопросе " Как мне сделать функцию свопинга в Java? ", и его ответ: Вы не можете . Такие языки, как C и C ++, могут предоставлять функции подкачки, потому что они, в отличие от Java, позволяют назначать из любую переменную , используя ссылку на эту переменную, что позволяет вам изменять ее значение (если не -const) без изменения содержимого объекта, на который он ранее ссылался.
Это может заставить вашу голову кружиться, пытаясь обдумать это до конца, но здесь ничего не происходит ...
- Переменные типа класса Java всегда являются "ссылками", которые фактически являются указателями.
- Java-указатели являются примитивными типами.
- Назначение Java всегда по значению базового примитива (в данном случае указатель).
- У Java просто нет механизма, эквивалентного передаче по ссылке C / C ++, который позволял бы вам косвенно изменять автономный примитивный тип, который может быть «указателем», таким как
this
.
Кроме того, интересно отметить, что C ++ на самом деле имеет два разных синтаксиса для передачи по ссылке. Один основан на явных указателях и был унаследован от языка Си. Другой основан на операторе C ++ ссылочного типа &
. [Существует также форма управления ссылками C ++ smart pointer , но это больше похоже на семантику в стиле Java - где сами ссылки передаются по значению.]
Примечание. В приведенном выше обсуждении assign-by и pass-by обычно являются взаимозаменяемыми. В основе любого назначения лежит концептуальная операторная функция , которая выполняет назначение на основе правого объекта, являющегося пройденным дюйм.
Итак, возвращаясь к исходному вопросу : Если бы вы могли присвоить this
в Java, это означало бы изменение значения ссылки, хранящейся в this
. Это фактически эквивалентно прямому присвоению this
в C ++, что также недопустимо в этом языке.
Как в Java, так и в C ++, this
фактически является указателем, который нельзя изменить. Java кажется другим, потому что он использует оператор .
для разыменования указателя - что, если вы привыкли к синтаксису C ++, создает впечатление, что это не один.
Вы можете, конечно, написать что-то на Java, похожее на конструктор копирования C ++ , но в отличие от C ++, нет способа обойти тот факт, что реализация должна быть предоставлена с точки зрения явной инициализации по элементам. [В C ++ вы можете избежать этого, в конечном счете, только потому, что компилятор предоставит вам для каждого члена реализацию оператора присваивания .]
ThОграничение Java, которое вы не можете скопировать в this
в целом, является искусственным. Вы можете достичь точно такого же результата, написав его для каждого члена, но у языка просто нет естественного способа указать такую операцию, которая будет выполняться с this
- синтаксис C ++ , (*this)
не имеет аналога в Java.
И, фактически, в Java нет встроенной операции, которая переназначает содержимое любого существующего объекта - даже если он не упоминается как this
. [Такая операция, вероятно, более важна для основанные на стеке объекты, такие как обычные в C ++.]
Относительно сценария использования глубокого копирования : Это сложно в Java .
Для C ++ - язык, ориентированный на значения. Семантическое намерение присваивания в целом очевидно. Если я говорю a=b
, я обычно хочу, чтобы a
стал независимым клоном из b
, содержащим равное значение . C ++ делает это автоматически для присваивания , и планирует автоматизировать процесс, а также для сравнения.
Для Java и других ссылочно-ориентированных языков копирование объекта в общем смысле имеет неоднозначное значение. За исключением примитивов, Java не делает различий между типами значений и ссылочными типами , поэтому при копировании объекта необходимо учитывать каждый вложенный член типа класса (включая родительский) и принимать решение по регистру. в каждом конкретном случае, если этот объект-член должен быть скопирован или просто указан. Если оставить реализации по умолчанию, очень вероятно, что результат будет не тем, что вы хотите.
Сравнение объектов на равенство в Java страдает от одинаковых неоднозначностей .
Исходя из всего этого, ответ на основной вопрос : почему я не могу скопировать объект с помощью простой, автоматически сгенерированной операции на this
, что по сути, у Java нет четкого представления о том, что означает копирование объекта .
Еще один момент, чтобы ответить на буквальный вопрос:
Каково обоснование решения не делать this
переменной?
Было бы просто бессмысленно это делать. Значение this
- это просто указатель, который был передан функции, и если вы смогли изменить значение this
, это не могло напрямую повлиять на какой-либо объект или ссылку, использованную для вызова этого метода. В конце концов, Java передается по значению.