It is a crucial point, but IMHO is worth understanding.
All OO languages always make copies of references, and never copy an object 'invisibly'. It would be much harder to write programs if OO languages worked any other way. For example, functions, and methods, could never update an object. Java, and most OO languages would be almost impossible to use without significant added complexity.
An object in a program is supposed to have some meaning. For example it represents something specific in the real physical world. It usually makes sense to have many references to the same thing. For example, my home address can be given to many people and organisations, and that address always refers to the same physical location. So the first point is, objects often represent something which is specific, real, or concrete; and so being able to have many references to the same thing is extremely useful. Otherwise it would be harder to write programs.
Every time you pass a
as an argument/parameter to another function e.g. calling
foo(Dog aDoggy);
or apply a method to a
, the underlying program code makes a copy of the reference, to produce a second reference to the same object.
Further, if code with a copied reference is in a different thread, then both can be used concurrently to access the same object.
So in most useful programs, there will be multiple references to the same object, because that is the semantics of most OO programming languages.
Now, if we think about it, because passing by reference is the only mechanism available in many OO languages (C++ supports both), we might expect it to be the 'right' default behaviour.
IMHO, using references is the right default, for a couple of reasons:
- It guarantees that the value of an object used in two different places is the same. Imagine putting an object into two different data structures (arrays, lists etc.), and doing some operations on an object that changes it. That could be a nightmare to debug. More importantly, it is the same object in both data structures, or the program has a bug.
- You can happily refactor code into several functions, or merge the code from several functions into one, and the semantics do not change. If the language did not provide reference semantics, it would be even more complex to modify code.
There is also an efficiency argument; making copies of entire objects is less efficient than copying a reference. However, I think that misses the point. Multiple references to the same object make more sense, and are easier to use, because they match the semantics of the real physical world.
So, IMHO, it usually makes sense to have multiple references to the same object. In the unusual cases where that doesn't make sense in the context of an algorithm, most languages provide the ability to make a 'clone' or deep copy. However that is not the default.
I think people who argue that this should not be the default are using a language which does not provide automatic garbage collection. For example, old fashioned C++. The issue there is that they need to find a way to collect 'dead' objects and not reclaim objects that may still be required; having multiple references to the same object makes that hard.
I think, if C++ had sufficiently low-cost garbage collection, so that all referenced objects are garbage collected, then much of the objection goes away. There will still be some cases where reference semantics is not what is needed. However, in my experience, the people who can identify those situations are also usually capable of choosing the appropriate semantics anyway.
I believe there is some evidence that a large amount of the code in a C++ program is there to handle or mitigate garbage collection. However, writing, and maintaining that sort of 'infrastructural' code adds cost; it is there to make the language easier to use, or more robust. So, for example the Go language is designed with a focus on remediating some of the weaknesses of C++, and it has no choice except garbage collection.
This is of course irrelevant in the context of Java. It too was designed to be easy to use, and so has garbage collection. Hence having multiple references is the default semantics, and is relatively safe in the sense that objects aren't reclaimed while there is a reference to them. Of course they might be held onto by a data structure because the program doesn't properly tidy-up when it has really finished with an object.
So, circling back around to your question (with a bit of generalisation), when would you want more than one references to the same object? Pretty much in every situation I can think of. They are the default semantics of most languages parameter passing mechanism. I suggest that is because the default semantics of handling objects which exists in the real world pretty much has to be by reference ('cos the actual objects are out there).
Any other semantics would be harder to handle.
Dog a = new Dog("rover"); // initialise with name
DogList dl = new DogList()
dl.add(a)
...
a.setOwner("Mr Been")
I suggest that the "rover" in dl
should be the one effected by setOwner
or programs get hard to write, understand, debug or modify. I think most programmers would be puzzled or dismayed otherwise.
later, the dog is sold:
soldDog = dl.lookupOwner("rover", "Mr Been")
soldDog.setOwner("Mr Mcgoo")
This sort of processing is common and normal. So reference semantics are the default because it usually makes most sense.
Summary: It always makes sense to have multiple references to the same object.
a
andb
always reference the sameDog
, then there is no point to it. If they sometimes might, then it is quite useful.