I have a query based on Sierra & Bates SCJP v6 Chapter 3 Question 5 and the effect of the final modifier. The essence of the query is the why the answer is correct. The notes to the question (pg 280) note that “The final modifier assures that a reference variable cannot be referred to a different object”.
I note that while f1 is not accessible from within the method FizzSwitch, the memory address of f1.x is. So when line 24 changes the initial x=5 to x=6 this is possible because fi, z and f3 refer to the same memory address. As shown in output “h)…”.
I experimented with removal of the final for f1 and z and still get the same output (i.e. h) ….chapter03.Fizz@3e25a5). It appears that the reasoning that it is due to the final modifier does not hold. Without either and both the memory address is always the same. Hence f1.x is changed regardless of the 'final' modifier or just ‘default’.
Code enclosed code for ease of reference
Note there are extra System.out.println() to show details during execution.
Which gives the output
a) f1.x= 5
b) f2.x= 5
e) paramater x= 5
e) paramater y= 5
h) z= chapter03.Fizz@3e25a5
f) z.x= 5
g) z.x= 6
c) f1.x= 6
c) f3.x= 6
c) f2.x= 5
h) f1= chapter03.Fizz@3e25a5
h) f3= chapter03.Fizz@3e25a5
Scott Gordon Sutherland wrote:I note that while f1 is not accessible from within the method FizzSwitch, the memory address of f1.x is. So when line 24 changes the initial x=5 to x=6 this is possible because fi, z and f3 refer to the same memory address. As shown in output “h)…”.
f1, z and f3 indeed all refer to the same object. Note that the "chapter03.Fizz@3e25a5" is not the memory address of an object; it is the hash code. Different objects can have the same hash code, so if you see two times the same code then there is in principle no guarantee that it is the exact same object (although it practically almost always is).
The final modifier just means that you cannot make f1 or z refer to any other object than the one that you initialized these variables with. It does not mean that you cannot change the content of the objects that these variables refer to, as you have noticed (i.e. it is not the same as const in C++).
Thanks for the quick reply, Yes you guessed I am thinking on the lines of C++ const
To clarify my understanding - while I could revise the value of f1.x by assigning f1.x = 7, or even f1.x = f2.x. 'final' modifier prevents me from assigning f1 = f2.?
1. What are the benefits of 'final' in this situation as f1.x = f2.x achieves the same end result as f1 = f2. Obviously this is trivial code, but the principle could be applied to more complex objects with many variables.
2. How would you completely protect an object from any changes as I've experiemented with making f1 'private' or 'protected' to limit access and they don't compile.
Scott Gordon Sutherland wrote:1. What are the benefits of 'final' in this situation as f1.x = f2.x achieves the same end result as f1 = f2.
I don't know what you mean exactly by that - f1.x = f2.x is something completely different from f1 = f2. The first sets the value of the member x of the object that f1 refers to, to the value of the member x of the object that f2 refers to. The second just makes f1 refer to the same object that f2 refers to. Note that f1 = f2 does not copy the content of an object, as it would in C++. Variables in Java are references to objects, they are not the objects themselves as in C++.
Java doesn't have anything like const in C++, which makes an object read-only. You'd have to design the class to be immutable - as Rob says, set the values of the members in the constructor, make the member variables final, don't provide any methods to change the member variables. Some classes in the standard Java API, such as class String, are designed as immutable classes. Making classes immutable has a number of advantages; one of them is that in multi-threaded programs you'll have to worry less about synchronization because multiple threads might want to modify the same object at the same time.