Reputation: 10304
I read with interest this question : Can I pass parameters by reference in Java?
What comes out it is that parameters (which are not primitives) are passed by copying the reference value. And so as the example states; you can't modify the reference of the parameter you gave:
Object o = "Hello";
mutate(o)
System.out.println(o); // Will print Hello
private void mutate(Object o) { o = "Goodbye"; } //NOT THE SAME o!
This kind of problem could be avoided using final
like this :
private void mutate(final Object o) { o = "Goodbye"; } //Compilation error
The questions :
final
keyword in such a case only used to throw a compilation error ? final
implicit or mandatory ?I rarely used final
for method parameters in Java but now I can't think of any case where you would voluntarily omit to put final
to a method parameter.
Thanks!
Upvotes: 3
Views: 1455
Reputation: 23903
To avoid this:
public void searchBiggest(String startingWith) {
for (String s : collection) {
if (s.startsWith(startingWith)) {
startingWith = s;
}
}
return startingWith;
}
As you can see it makes the code not intuitive because the parameter could be holding a different value that the one passed.
From Hard Core Java - Chapter 2:
Little bugs like this are often the most difficult to locate. By Murphy’s Law, you can absolutely guarantee that this code will be in the middle of a huge piece of your project, and the error reports won’t directly lead you here. What’s more, you proba- bly won’t notice the impact of the bug until it goes into production and users are screaming for a fix.
You cannot afford to forget that once you write code, the story is not over. People will make changes, additions, and errors in your code. You will have to look through the code and fix everything that was messed up. To prevent this problem from occur- ring, do the following:
and a similar sample is done using the parameter, and additionally invoking other methods with the parameter (already changed).
Upvotes: 4
Reputation: 33534
1. You are passing the Object Reference Variable
as the Argument, when you invoked the method by calling it.
mutate(o);
2. By using the final
keyword on the Parameter
in the Method Definition, you have made it final, So it means that local Object Reference Variable o
which is of type Object is final, so this variable can't be used to point any other object.
(Note: Its the Object Reference Variable
which is final
, Not the Object on the HEAP)
mutate(final Object o)
3. You can assign the object associated with the Object Reference Variable o to some other Object Reference Variable and then change it.
Object i = o;
i = "GoodBye";
Upvotes: 2
Reputation: 272297
I usually do this to prevent accidental or unintended modifications of this reference. e.g.
private String doSomething(final String arg) {
// final to prevent me doing something stupid!
}
One interesting scenario is in setters. You want to ensure that you set the member variable and not the arg passed in. e.g.
public void setArg(String arg) {
_arg = arg;
}
In the above scenario, if the method parameter is not final, then I could possibly set
arg = arg;
by mistake. The above is a common typo, or can occur due to search/replace refactoring. By making arg
final, you can't accidentally reassign it.
Upvotes: 4
Reputation: 340743
Typically you shouldn't modify parameters as it can introduce hard to find bugs. However there are some useful idioms and situations where it can be useful:
public void print(String msg, int count) {
msg = (msg != null)? msg : "Default";
while(--count >= 0) {
System.out.println(msg);
}
}
Upvotes: 2
Reputation: 19225
Java passes by value. So when you call mutate, a copy of o is passed.
Inside mutate, the copy of o is then set to point to "Goodbye". The original o is unchanged.
Setting the parameter to be final will not change this, but it will, as you've seen, stop reassignment of the copy of the original reference. Thats not the same, however, as stopping reassignment of the original reference.
Upvotes: 2