Steve M
Steve M

Reputation: 9784

Final parameters in a constructor in Java

I am learning about classes and constructors in Java. I messing around with the code in an example program and can't seem to figure out exactly what's going on.

This code won't compile which makes sense to me:

class Line {
Point start;
Point end;

Line(final Point start, final Point end) {

    this.start = new Point(start);
    this.end = new Point(end);
    start = new Point(0.4, 0.4);

}...

I'm trying to assign the original start Point object reference to another Point object by calling the constructor of the Point object. The final keyword is in conflict with this.

However when I remove the final keyword from the Point start parameter...

class Line {
Point start;
Point end;

Line(Point start, final Point end) {

    this.start = new Point(start);
    this.end = new Point(end);
    start = new Point(0.4, 0.4);

}

it doesn't seem to actually change the reference, the Point object that is passed to the Line constructor still seems to point to the original object and is unchanged by the code of the Line constructor. So what gives? Does this have something to do with the fact that the 'start' referred to is local in scope to the Line constructor?

Upvotes: 3

Views: 5834

Answers (5)

David Lee
David Lee

Reputation: 879

When you modify "start" by doing "this.start = new Point(start)" after initialization from "Line(Point start, final Point end) {" you're not replacing the actual object on heap which what "start" points to but allocating new Point object on heap on separate area from the existing and modifying the existing pointer "start"(scalar type on STACK) to point to newly allocated.

Constructor is a special purpose method (function) that is called by java's new operator after object allocation on java heap. So when a method is called, stack is allocated and any scalar types (in java it's primitive types like int, double, char...) and REFERENCE in the method are allocated on the stack (not heap). When you write statments as "final Object o = new Object()", you've allocated two things on memory.
First, "new Object()" on java heap. (HEAP)
Second, pointer to above in stack which is "Object o". (STACK)
In your case, you just tried to overwrite "final Object o" which is scalar type and read only on jvm memory(STACK).

class Line {
Point start;
Point end;

// On the first line "Line(Point start, Point end) {",
// two references and two actual Objects that references point to
// are already allocated in memory.  
// So you've allocated four things.
Line(Point start, final Point end) { // "start" initialized on stack as final
    this.start = new Point(start); // tried to modify final variable on stack.
    this.end = new Point(end);
    start = new Point(0.4, 0.4);

}

Upvotes: 0

Bhesh Gurung
Bhesh Gurung

Reputation: 51030

That variable is local to the constructor. So, assigning it a new reference doesn't make sense outside the constructor because it doesn't exist outside the constructor.

One way to achieve that kind of effect is to wrap it up in another object. And pass reference to the mutable wrapper.

Upvotes: 0

andreban
andreban

Reputation: 4976

When you do "start = new Point(0.4, 0.4);", you are referencing the start that was received on the constructor. As the constructor defines it as final, its illegal to assign a new value to the variable.

The detail is that as java uses the pass-by-value approach, even if you don't use final and change the value inside the constructor, the value of the original value (the one you passed as parameter to the method) is still the same.

Upvotes: 0

jlordo
jlordo

Reputation: 37813

it doesn't seem to actually change the reference

You can't change the reference of a parameter you use to call a method inside that method itself. The value of the parameter (which is a reference to an object) is copied into the method parameter, so you have a second reference to the same object. Inside the method you can only modify the second reference and can't change the original reference. The only thing you can do is the modifiy the referenced object.

Upvotes: 0

Mik378
Mik378

Reputation: 22171

Java don't use pass-by-reference, it uses ALWAYS pass-by-value. Actually, references type in Java are simply pointers and does not share at all the same meaning as References in C# for instance.

So when you do this statement in your constructor:

start = new Point(0.4, 0.4);

The original Point passing in argument IS NOT changed. However, the local variable (meaning the paramater) will point to the new Point defined by coordinates: 0,4, 0,4.

For better understanding, read this article: Java is Pass-by-Value, Dammit!

Upvotes: 5

Related Questions