In Java, a variable can either hold a primitive type or a reference of an object. This holds true for all cases. Primitive types are stored in stack and objects are stored in heap. To store objects, it needs to maintain their structure.
We’ve always heard that a variable can be passed by value or passed by reference. But, essentially, in Java, there is no such thing as pass-by-reference. It always passes variables by value. But, you need to see what the variable holds. If it holds primitive type then we call it to pass by value or in the case of the reference of an object, we call it to pass by reference. However, it always passes the copy of whatever it holds.
Remember that whenever a variable is passed, its copy will be passed. And, if the variable contains the pointer of an object then the copy will also contain the same pointer. So, if we change anything in the referred object, it will also reflect all variables that hold the same pointer
Final Variables and Const Correctness
Final variables in java are not essentially final. I know we cannot change the value assigned to the variable but if you assign a reference to an object. Then, we can change the referred object without changing the reference which the final variable holds. This is against the concept of const correctness.
Const correctness is basically the concept that if you pass a final variable to a function and the function is able to modify the state of the referred object. Then, the language lacks const correctness.