The error I get from the compiler is "The left hand side of an assignment must be a variable". My use case is deep copying, but is not really relevant.
In C++, one can assign to *this
.
The question is not how to circumvent assignment to this
. It's very simple, but rather what rationale is there behind the decision not to make this
a variable.
Are the reasons technical or conceptual?
My guess so far - the possibility of rebuilding an Object in a random method is error-prone (conceptual), but technically possible.
EDIT Please restrain from variations of "because java specs say so". I would like to know the reason for the decision
The
this
in Java is a part of the language, a key word, not a simple variable. It was made for accessing an object from one of its methods, not another object. Assigning another object to it would cause a mess. If you want to save another objects reference in your object, just create a new variable.The reason is just conceptual.
this
was made for accessing an Object itself, for example to return it in a method. Like I said, it would cause a mess if you would assign another reference to it. Tell me a reason why alteringthis
would make sense.Yes, but you can't do
this = something
in C++, which I actually believe is a closer match for what you're asking about on the Java side here.I would say clarity / readability.
this
was chosen to be a reserved word, probably since it's not passed as an explicit argument to a method. Using it as an ordinary parameter and being able to reassign a new value to it, would mess up readability severely.In fact, many people argue that you shouldn't change argument-variables at all, for this very reason.
Mostly conceptual I would presume. A few technical quirks would arise though. If you could reassign a value to
this
, you could completely hide instance variables behind local variables for example.I'm not sure I understand this statement fully, but yes, error prone is probably the primary reason behind the decision to make it a keyword and not a variable.
IMO, conceptual.
The
this
keyword is a short hand for "the reference to the object whose method you are currently executing". You can't change what that object is. It simply makes no sense in the Java execution model.Since it makes no sense for
this
to change, there is no sense in making it a variable.(Note that in C++ you are assigning to
*this
, notthis
. And in Java there is no*
operator and no real equivalent to it.)If you take the view that you could change the target object for a method in mid flight, then here are some counter questions.
What is the use of doing this? What problems would this (hypothetical) linguistic feature help you solve ... that can't be solved in a more easy-to-understand way?
How would you deal with mutexes? For instance, what would happen if you assign to
this
in the middle of a synchronized method ... and does the proposed semantic make sense? (The problem is that you either end up executing in synchronized method on an object that you don't have a lock on ... or you have to unlock the oldthis
and lock the newthis
with the complications that that entails. And besides, how does this make sense in terms of what mutexes are designed to achieve?)How would you make sense of something like this:
Sure you can ascribe a semantic to this but:
If you try seriously to answer these questions, I expect you'll come to the conclusion that it would have been a bad idea to implement this. (But if you do have satisfactory answers, I'd encourage you to write them up and post them as your own Answer to your Question!)
But in reality, I doubt that the Java designers even gave this idea more than a moment's consideration. (And rightly so, IMO)
The
*this = ...
form of C++ is really just a shorthand for a sequence of assignments of the the attributes of the current object. We can already do that in Java ... with a sequence of normal assignments. There is certainly no need for new syntax to support this. (How often does a class reinitialize itself from the state of another class?)I note that you commented thus:
That won't work.
The value of
this
is (effectively) passed by value to the method when the method is invoked. The callee doesn't know where thethis
reference came from.Even if it did, that's only one place where the reference is held. Unless
null
is assigned in all places, the object cannot be eligible of garbage collection.Ignoring the fact that this is technically impossible, I do not think that your idea would be useful OR conducive to writing readable / maintainable code. Consider this:
Why would you want to do that? Supposing that the method name was something innocuous rather than
kill
, would you expect the method to be able to zap the value ofmine
?I don't. In fact, I think that this would be a misfeature: useless and dangerous.
Even without these nasty "make it unreachable" semantics, I don't actually see any good use-cases for modifying
this
.Assigning to
(*this)
in C++ performs a copy operation -- treating the object as a value-type.Java does not use the concept of a value-type for classes. Object assignment is always by-reference.
To copy an object as if it were a value-type: How do I copy an object in Java?
The terminology used for Java is confusing though: Is Java “pass-by-reference” or “pass-by-value”
Answer: Java passes references by value. (from here)
In other words, because Java never treats non-primitives as value-types, every class-type variable is a reference (effectively a pointer).
So when I say, "object assignment is always by-reference", it might be more technically accurate to phrase that as "object assignment is always by the value of the reference".
The practical implication of the distinction drawn by Java always being pass-by-value is embodied in the question "How do I make my swap function in java?", and its answer: You can't. Languages such as C and C++ are able to provide swap functions because they, unlike Java, allow you to assign from any variable by using a reference to that variable -- thus allowing you to change its value (if non-const) without changing the contents of the object that it previously referenced.
It could make your head spin to try to think this all the way through, but here goes nothing...
Additionally, it is interesting to note that C++ actually has two different syntaxes for pass-by-reference. One is based on explicit pointers, and was inherited from the C language. The other is based on the C++ reference-type operator
&
. [There is also the C++ smart pointer form of reference management, but that is more akin to Java-like semantics -- where the references themselves are passed by value.]Note: In the above discussion assign-by and pass-by are generally interchangeable terminology. Underlying any assignment, is a conceptual operator function that performs the assignment based on the right-hand-side object being passed in.
So coming back to the original question: If you could assign to
this
in Java, that would imply changing the value of the reference held bythis
. That is actually equivalent to assigning directly tothis
in C++, which is not legal in that language either.In both Java and C++,
this
is effectively a pointer that cannot be modified. Java seems different because it uses the.
operator to dereference the pointer -- which, if you're used to C++ syntax, gives you the impression that it isn't one.You can, of course, write something in Java that is similar to a C++ copy constructor, but unlike with C++, there is no way of getting around the fact that the implementation will need to be supplied in terms of an explicit member-wise initialization. [In C++ you can avoid this, ultimately, only because the compiler will provide a member-wise implementation of the assignment operator for you.]
The Java limitation that you can't copy to
this
as a whole is sort-of artificial though. You can achieve exactly the same result by writing it out member-wise, but the language just doesn't have a natural way of specifying such an operation to be performed on athis
-- the C++ syntax,(*this)
doesn't have an analogue in Java. And, in fact, there is no built-in operation in Java that reassigns the contents of any existing object -- even if it's not referred to asthis
. [Such an operation is probably more important for stack-based objects such as are common in C++.]Regarding the use-case of performing a deep copy: It's complicated in Java.
For C++, a value-type-oriented language. The semantic intention of assignment is generally obvious. If I say
a=b
, I typically wanta
to become and independent clone ofb
, containing an equal value. C++ does this automatically for assignment, and there are plans to automate the process, also, for the comparison.For Java, and other reference-oriented languages, copying an object, in a generic sense, has ambiguous meaning. Primitives aside, Java doesn't differentiate between value-types and reference-types, so copying an object has to consider every nested class-type member (including those of the parent) and decide, on a case-by-case basis, if that member object should be copied or just referenced. If left to default implementations, there is a very good chance that result would not be what you want. Comparing objects for equality in Java suffers from the same ambiguities.
Based on all of this, the answer to the underlying question: why can't I copy an object by some simple, automatically generated, operation on
this
, is that fundamentally, Java doesn't have a clear notion of what it means to copy an object.One last point, to answer the literal question:
It would simply be pointless to do so. The value of
this
is just a pointer that has been passed to a function, and if you were able to change the value ofthis
, it could not directly affect whatever object, or reference, was used to invoke that method. After all, Java is pass-by-value.Assigning to
*this
in C++ isn't equivalent to assigningthis
in Java. Assigningthis
is, and it isn't legal in either language.becausethis
isfinal
,this
is keyword, not a variable. and you can't assign something to keyword. now for a min consider if it were a reference variable in design spec..and see the example belowand it holds implicit reference to the object calling method. and it is used for reference purpose only, now consider you assign something to
this
so won't it break everything ?Example
consider the following code from
String
class (Note: below code contains compilation error it is just to demonstrate OP the situation)