This question is about copy constructors: let’s say that you are given the following two accessor methods that belong to a class called SomeClass. An accessor method is simply a method used to get access to the instance variables of a class:
You can assume that leapYear is a private instance variable of the Year class, and lastName is a private instance variable of the String class. Why is it that a copy constructor is being called in the second method, but not in the first? Why even use a copy constructor in the first place?
Before we explain this problem further, it helps to define a copy constructor: A copy constructor is a constructor that takes only one parameter which is the same exact type as the class in which the copy constructor is defined. For example, suppose we define a class called X. Then, a copy constructor defined in class X would also expect a parameter of type X. In the example above, the statement "return new Year(leapYear);" is using a copy constructor because Year is a class and leapYear is an object of the Year class.
A copy constructor is used to create another object that is a copy of the object that it takes as a parameter. But, the newly created copy is actually independent of the original object. It is independent in the sense that the copy is located at a completely different address in memory than the original.
Why copy constructors are used
So, why is it that the second method (getYear) is using a copy constructor? Let’s say we redefined getYear, so that it doesn’t use a copy constructor. It would look like this:
The problem here is that a reference to the private instance variable ‘leapYear’ is being returned. This means that anyone could declare a SomeClass object, call the accessor method getYear() with that object and assign the return value to a Year object. The danger with this is that the Year object now holds a reference to what was supposed to be a private instance variable (leapYear), thereby violating its privacy. This is shown below:
By using a copy constructor in the definition of getYear(), a separate Year object is created entirely. This object has the same values stored in the instance variables as the original leapYear object, but with its own address space. This way the original leapYear is safe.
In the getName() method defined above, it looks like we will encounter the same problem, because we are returning a reference to a private instance variable. So now the question is why isn’t a copy constructor being used in the method getName()?
The answer is that it simply does not need a copy constructor because the value of the instance variable "lastName" can not be changed, even if we have a reference to it. This is because the String class is what’s called an immutable class – which means that it contains no mutator methods that would allow us to change any String object. So, even with the reference, we can’t modify "lastName". This is why it’s perfectly safe to return a reference to "lastName" even though it’s a private instance variable.